smb3: fix mode passed in on create for modetosid mount option

When using the special SID to store the mode bits in an ACE (See
http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx)
which is enabled with mount parm "modefromsid" we were not
passing in the mode via SMB3 create (although chmod was enabled).
SMB3 create allows a security descriptor context to be passed
in (which is more atomic and thus preferable to setting the mode
bits after create via a setinfo).

This patch enables setting the mode bits on create when using
modefromsid mount option. In addition it fixes an endian
error in the definition of the Control field flags in the SMB3
security descriptor. It also makes the ACE type of the special
SID better match the documentation (and behavior of servers
which use this to store mode bits in SMB3 ACLs).

Signed-off-by: Steve French <stfrench@microsoft.com>
Acked-by: Ronnie Sahlberg <lsahlber@redhat.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>

Changed files
+122 -34
fs
+26 -16
fs/cifs/cifsacl.c
··· 802 return; 803 } 804 805 806 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, 807 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) ··· 840 if (modefromsid) { 841 struct cifs_ace *pntace = 842 (struct cifs_ace *)((char *)pnndacl + size); 843 - int i; 844 845 - pntace->type = ACCESS_ALLOWED; 846 - pntace->flags = 0x0; 847 - pntace->access_req = 0; 848 - pntace->sid.num_subauth = 3; 849 - pntace->sid.revision = 1; 850 - for (i = 0; i < NUM_AUTHS; i++) 851 - pntace->sid.authority[i] = 852 - sid_unix_NFS_mode.authority[i]; 853 - pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; 854 - pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; 855 - pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); 856 - 857 - /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ 858 - pntace->size = cpu_to_le16(28); 859 - size += 28; 860 num_aces++; 861 } 862
··· 802 return; 803 } 804 805 + /* 806 + * Fill in the special SID based on the mode. See 807 + * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx 808 + */ 809 + unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) 810 + { 811 + int i; 812 + unsigned int ace_size = 28; 813 + 814 + pntace->type = ACCESS_DENIED_ACE_TYPE; 815 + pntace->flags = 0x0; 816 + pntace->access_req = 0; 817 + pntace->sid.num_subauth = 3; 818 + pntace->sid.revision = 1; 819 + for (i = 0; i < NUM_AUTHS; i++) 820 + pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i]; 821 + 822 + pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; 823 + pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; 824 + pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); 825 + 826 + /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ 827 + pntace->size = cpu_to_le16(ace_size); 828 + return ace_size; 829 + } 830 831 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, 832 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) ··· 815 if (modefromsid) { 816 struct cifs_ace *pntace = 817 (struct cifs_ace *)((char *)pnndacl + size); 818 819 + size += setup_special_mode_ACE(pntace, nmode); 820 num_aces++; 821 } 822
+16 -16
fs/cifs/cifsacl.h
··· 147 } __packed; 148 149 /* Meaning of 'Control' field flags */ 150 - #define ACL_CONTROL_SR 0x0001 /* Self relative */ 151 - #define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */ 152 - #define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */ 153 - #define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */ 154 - #define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */ 155 - #define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */ 156 - #define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */ 157 - #define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */ 158 - #define ACL_CONTROL_SS 0x0100 /* Create server ACL */ 159 - #define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */ 160 - #define ACL_CONTROL_SD 0x0400 /* SACL defaulted */ 161 - #define ACL_CONTROL_SP 0x0800 /* SACL is present on object */ 162 - #define ACL_CONTROL_DD 0x1000 /* DACL defaulted */ 163 - #define ACL_CONTROL_DP 0x2000 /* DACL is present on object */ 164 - #define ACL_CONTROL_GD 0x4000 /* Group was defaulted */ 165 - #define ACL_CONTROL_OD 0x8000 /* User was defaulted */ 166 167 /* Meaning of AclRevision flags */ 168 #define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
··· 147 } __packed; 148 149 /* Meaning of 'Control' field flags */ 150 + #define ACL_CONTROL_SR 0x8000 /* Self relative */ 151 + #define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */ 152 + #define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */ 153 + #define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */ 154 + #define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */ 155 + #define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */ 156 + #define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */ 157 + #define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */ 158 + #define ACL_CONTROL_SS 0x0080 /* Create server ACL */ 159 + #define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */ 160 + #define ACL_CONTROL_SD 0x0020 /* SACL defaulted */ 161 + #define ACL_CONTROL_SP 0x0010 /* SACL is present on object */ 162 + #define ACL_CONTROL_DD 0x0008 /* DACL defaulted */ 163 + #define ACL_CONTROL_DP 0x0004 /* DACL is present on object */ 164 + #define ACL_CONTROL_GD 0x0002 /* Group was defaulted */ 165 + #define ACL_CONTROL_OD 0x0001 /* User was defaulted */ 166 167 /* Meaning of AclRevision flags */ 168 #define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
+1
fs/cifs/cifsproto.h
··· 213 const struct cifs_fid *, u32 *); 214 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, 215 const char *, int); 216 217 extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); 218 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
··· 213 const struct cifs_fid *, u32 *); 214 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, 215 const char *, int); 216 + extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); 217 218 extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); 219 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
+69 -2
fs/cifs/smb2pdu.c
··· 2191 return 0; 2192 } 2193 2194 static struct crt_query_id_ctxt * 2195 create_query_id_buf(void) 2196 { ··· 2629 return rc; 2630 } 2631 2632 - if ((oparms->disposition == FILE_CREATE) && 2633 (oparms->mode != ACL_NO_MODE)) { 2634 if (n_iov > 2) { 2635 struct create_context *ccontext = ··· 2638 cpu_to_le32(iov[n_iov-1].iov_len); 2639 } 2640 2641 - /* rc = add_sd_context(iov, &n_iov, oparms->mode); */ 2642 if (rc) 2643 return rc; 2644 }
··· 2191 return 0; 2192 } 2193 2194 + /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ 2195 + static struct crt_sd_ctxt * 2196 + create_sd_buf(umode_t mode, unsigned int *len) 2197 + { 2198 + struct crt_sd_ctxt *buf; 2199 + struct cifs_ace *pace; 2200 + unsigned int sdlen, acelen; 2201 + 2202 + *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8); 2203 + buf = kzalloc(*len, GFP_KERNEL); 2204 + if (buf == NULL) 2205 + return buf; 2206 + 2207 + sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + 2208 + sizeof(struct cifs_ace); 2209 + 2210 + buf->ccontext.DataOffset = cpu_to_le16(offsetof 2211 + (struct crt_sd_ctxt, sd)); 2212 + buf->ccontext.DataLength = cpu_to_le32(sdlen); 2213 + buf->ccontext.NameOffset = cpu_to_le16(offsetof 2214 + (struct crt_sd_ctxt, Name)); 2215 + buf->ccontext.NameLength = cpu_to_le16(4); 2216 + /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ 2217 + buf->Name[0] = 'S'; 2218 + buf->Name[1] = 'e'; 2219 + buf->Name[2] = 'c'; 2220 + buf->Name[3] = 'D'; 2221 + buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */ 2222 + /* 2223 + * ACL is "self relative" ie ACL is stored in contiguous block of memory 2224 + * and "DP" ie the DACL is present 2225 + */ 2226 + buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP); 2227 + 2228 + /* offset owner, group and Sbz1 and SACL are all zero */ 2229 + buf->sd.OffsetDacl = cpu_to_le32(sizeof(struct smb3_sd)); 2230 + buf->acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */ 2231 + 2232 + /* create one ACE to hold the mode embedded in reserved special SID */ 2233 + pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); 2234 + acelen = setup_special_mode_ACE(pace, (__u64)mode); 2235 + buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); 2236 + buf->acl.AceCount = cpu_to_le16(1); 2237 + return buf; 2238 + } 2239 + 2240 + static int 2241 + add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) 2242 + { 2243 + struct smb2_create_req *req = iov[0].iov_base; 2244 + unsigned int num = *num_iovec; 2245 + unsigned int len = 0; 2246 + 2247 + iov[num].iov_base = create_sd_buf(mode, &len); 2248 + if (iov[num].iov_base == NULL) 2249 + return -ENOMEM; 2250 + iov[num].iov_len = len; 2251 + if (!req->CreateContextsOffset) 2252 + req->CreateContextsOffset = cpu_to_le32( 2253 + sizeof(struct smb2_create_req) + 2254 + iov[num - 1].iov_len); 2255 + le32_add_cpu(&req->CreateContextsLength, len); 2256 + *num_iovec = num + 1; 2257 + return 0; 2258 + } 2259 + 2260 static struct crt_query_id_ctxt * 2261 create_query_id_buf(void) 2262 { ··· 2563 return rc; 2564 } 2565 2566 + if ((oparms->disposition != FILE_OPEN) && 2567 (oparms->mode != ACL_NO_MODE)) { 2568 if (n_iov > 2) { 2569 struct create_context *ccontext = ··· 2572 cpu_to_le32(iov[n_iov-1].iov_len); 2573 } 2574 2575 + cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); 2576 + rc = add_sd_context(iov, &n_iov, oparms->mode); 2577 if (rc) 2578 return rc; 2579 }
+10
fs/cifs/smb2pdu.h
··· 25 #define _SMB2PDU_H 26 27 #include <net/sock.h> 28 29 /* 30 * Note that, due to trying to use names similar to the protocol specifications, ··· 855 struct create_context ccontext; 856 __u8 Name[8]; 857 } __packed; 858 859 #define COPY_CHUNK_RES_KEY_SIZE 24 860 struct resume_key_req {
··· 25 #define _SMB2PDU_H 26 27 #include <net/sock.h> 28 + #include <cifsacl.h> 29 30 /* 31 * Note that, due to trying to use names similar to the protocol specifications, ··· 854 struct create_context ccontext; 855 __u8 Name[8]; 856 } __packed; 857 + 858 + struct crt_sd_ctxt { 859 + struct create_context ccontext; 860 + __u8 Name[8]; 861 + struct smb3_sd sd; 862 + struct smb3_acl acl; 863 + /* Followed by at least 4 ACEs */ 864 + } __packed; 865 + 866 867 #define COPY_CHUNK_RES_KEY_SIZE 24 868 struct resume_key_req {