aboutsummaryrefslogtreecommitdiff
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsacl.c42
-rw-r--r--fs/cifs/cifsacl.h32
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/smb2pdu.c71
-rw-r--r--fs/cifs/smb2pdu.h10
5 files changed, 122 insertions, 34 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 06ffe52bdcfa..96ae72b556ac 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -802,6 +802,31 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
return;
}
+/*
+ * Fill in the special SID based on the mode. See
+ * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
+{
+ int i;
+ unsigned int ace_size = 28;
+
+ pntace->type = ACCESS_DENIED_ACE_TYPE;
+ pntace->flags = 0x0;
+ pntace->access_req = 0;
+ pntace->sid.num_subauth = 3;
+ pntace->sid.revision = 1;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
+
+ pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
+ pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
+ pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
+
+ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
+ pntace->size = cpu_to_le16(ace_size);
+ return ace_size;
+}
static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
@@ -815,23 +840,8 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
if (modefromsid) {
struct cifs_ace *pntace =
(struct cifs_ace *)((char *)pnndacl + size);
- int i;
- pntace->type = ACCESS_ALLOWED;
- pntace->flags = 0x0;
- pntace->access_req = 0;
- pntace->sid.num_subauth = 3;
- pntace->sid.revision = 1;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] =
- sid_unix_NFS_mode.authority[i];
- pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
- pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
- pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
-
- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
- pntace->size = cpu_to_le16(28);
- size += 28;
+ size += setup_special_mode_ACE(pntace, nmode);
num_aces++;
}
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 439b99cefeb0..21d7dee98d01 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -147,22 +147,22 @@ struct smb3_sd {
} __packed;
/* Meaning of 'Control' field flags */
-#define ACL_CONTROL_SR 0x0001 /* Self relative */
-#define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */
-#define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */
-#define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */
-#define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */
-#define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */
-#define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */
-#define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */
-#define ACL_CONTROL_SS 0x0100 /* Create server ACL */
-#define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */
-#define ACL_CONTROL_SD 0x0400 /* SACL defaulted */
-#define ACL_CONTROL_SP 0x0800 /* SACL is present on object */
-#define ACL_CONTROL_DD 0x1000 /* DACL defaulted */
-#define ACL_CONTROL_DP 0x2000 /* DACL is present on object */
-#define ACL_CONTROL_GD 0x4000 /* Group was defaulted */
-#define ACL_CONTROL_OD 0x8000 /* User was defaulted */
+#define ACL_CONTROL_SR 0x8000 /* Self relative */
+#define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */
+#define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */
+#define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */
+#define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */
+#define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */
+#define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */
+#define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */
+#define ACL_CONTROL_SS 0x0080 /* Create server ACL */
+#define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */
+#define ACL_CONTROL_SD 0x0020 /* SACL defaulted */
+#define ACL_CONTROL_SP 0x0010 /* SACL is present on object */
+#define ACL_CONTROL_DD 0x0008 /* DACL defaulted */
+#define ACL_CONTROL_DP 0x0004 /* DACL is present on object */
+#define ACL_CONTROL_GD 0x0002 /* Group was defaulted */
+#define ACL_CONTROL_OD 0x0001 /* User was defaulted */
/* Meaning of AclRevision flags */
#define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1ed695336f62..9c229408a251 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -213,6 +213,7 @@ extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
const struct cifs_fid *, u32 *);
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
const char *, int);
+extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 187a5ce68806..b77643e02157 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2191,6 +2191,72 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
return 0;
}
+/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
+static struct crt_sd_ctxt *
+create_sd_buf(umode_t mode, unsigned int *len)
+{
+ struct crt_sd_ctxt *buf;
+ struct cifs_ace *pace;
+ unsigned int sdlen, acelen;
+
+ *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8);
+ buf = kzalloc(*len, GFP_KERNEL);
+ if (buf == NULL)
+ return buf;
+
+ sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +
+ sizeof(struct cifs_ace);
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct crt_sd_ctxt, sd));
+ buf->ccontext.DataLength = cpu_to_le32(sdlen);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct crt_sd_ctxt, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
+ buf->Name[0] = 'S';
+ buf->Name[1] = 'e';
+ buf->Name[2] = 'c';
+ buf->Name[3] = 'D';
+ buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */
+ /*
+ * ACL is "self relative" ie ACL is stored in contiguous block of memory
+ * and "DP" ie the DACL is present
+ */
+ buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP);
+
+ /* offset owner, group and Sbz1 and SACL are all zero */
+ buf->sd.OffsetDacl = cpu_to_le32(sizeof(struct smb3_sd));
+ buf->acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
+
+ /* create one ACE to hold the mode embedded in reserved special SID */
+ pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);
+ acelen = setup_special_mode_ACE(pace, (__u64)mode);
+ buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);
+ buf->acl.AceCount = cpu_to_le16(1);
+ return buf;
+}
+
+static int
+add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+ unsigned int len = 0;
+
+ iov[num].iov_base = create_sd_buf(mode, &len);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = len;
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, len);
+ *num_iovec = num + 1;
+ return 0;
+}
+
static struct crt_query_id_ctxt *
create_query_id_buf(void)
{
@@ -2563,7 +2629,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
return rc;
}
- if ((oparms->disposition == FILE_CREATE) &&
+ if ((oparms->disposition != FILE_OPEN) &&
(oparms->mode != ACL_NO_MODE)) {
if (n_iov > 2) {
struct create_context *ccontext =
@@ -2572,7 +2638,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
cpu_to_le32(iov[n_iov-1].iov_len);
}
- /* rc = add_sd_context(iov, &n_iov, oparms->mode); */
+ cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
+ rc = add_sd_context(iov, &n_iov, oparms->mode);
if (rc)
return rc;
}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index fa2533da316d..7b1c379fdf7a 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -25,6 +25,7 @@
#define _SMB2PDU_H
#include <net/sock.h>
+#include <cifsacl.h>
/*
* Note that, due to trying to use names similar to the protocol specifications,
@@ -855,6 +856,15 @@ struct crt_query_id_ctxt {
__u8 Name[8];
} __packed;
+struct crt_sd_ctxt {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct smb3_sd sd;
+ struct smb3_acl acl;
+ /* Followed by at least 4 ACEs */
+} __packed;
+
+
#define COPY_CHUNK_RES_KEY_SIZE 24
struct resume_key_req {
char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];