diff options
| -rw-r--r-- | fs/cifs/cifsacl.c | 42 | ||||
| -rw-r--r-- | fs/cifs/cifsacl.h | 32 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 71 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.h | 10 | 
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]; |