| From 643fbceef48e5b22bf8e0905f903e908b5d2ba69 Mon Sep 17 00:00:00 2001 |
| From: Steve French <stfrench@microsoft.com> |
| Date: Thu, 16 Jan 2020 19:55:33 -0600 |
| Subject: smb3: fix default permissions on new files when mounting with modefromsid |
| |
| From: Steve French <stfrench@microsoft.com> |
| |
| commit 643fbceef48e5b22bf8e0905f903e908b5d2ba69 upstream. |
| |
| When mounting with "modefromsid" mount parm most servers will require |
| that some default permissions are given to users in the ACL on newly |
| created files, files created with the new 'sd context' - when passing in |
| an sd context on create, permissions are not inherited from the parent |
| directory, so in addition to the ACE with the special SID which contains |
| the mode, we also must pass in an ACE allowing users to access the file |
| (GENERIC_ALL for authenticated users seemed like a reasonable default, |
| although later we could allow a mount option or config switch to make |
| it GENERIC_ALL for EVERYONE special sid). |
| |
| CC: Stable <stable@vger.kernel.org> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Reviewed-By: Ronnie Sahlberg <lsahlber@redhat.com> |
| Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/cifs/cifsacl.c | 20 ++++++++++++++++++++ |
| fs/cifs/cifsproto.h | 1 + |
| fs/cifs/smb2pdu.c | 11 ++++++++--- |
| 3 files changed, 29 insertions(+), 3 deletions(-) |
| |
| --- a/fs/cifs/cifsacl.c |
| +++ b/fs/cifs/cifsacl.c |
| @@ -802,6 +802,26 @@ static void parse_dacl(struct cifs_acl * |
| return; |
| } |
| |
| +unsigned int setup_authusers_ACE(struct cifs_ace *pntace) |
| +{ |
| + int i; |
| + unsigned int ace_size = 20; |
| + |
| + pntace->type = ACCESS_ALLOWED_ACE_TYPE; |
| + pntace->flags = 0x0; |
| + pntace->access_req = cpu_to_le32(GENERIC_ALL); |
| + pntace->sid.num_subauth = 1; |
| + pntace->sid.revision = 1; |
| + for (i = 0; i < NUM_AUTHS; i++) |
| + pntace->sid.authority[i] = sid_authusers.authority[i]; |
| + |
| + pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0]; |
| + |
| + /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ |
| + pntace->size = cpu_to_le16(ace_size); |
| + return ace_size; |
| +} |
| + |
| /* |
| * Fill in the special SID based on the mode. See |
| * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx |
| --- a/fs/cifs/cifsproto.h |
| +++ b/fs/cifs/cifsproto.h |
| @@ -213,6 +213,7 @@ extern struct cifs_ntsd *get_cifs_acl_by |
| const struct cifs_fid *, u32 *); |
| extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, |
| const char *, int); |
| +extern unsigned int setup_authusers_ACE(struct cifs_ace *pace); |
| extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); |
| |
| extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); |
| --- a/fs/cifs/smb2pdu.c |
| +++ b/fs/cifs/smb2pdu.c |
| @@ -2199,13 +2199,14 @@ create_sd_buf(umode_t mode, unsigned int |
| struct cifs_ace *pace; |
| unsigned int sdlen, acelen; |
| |
| - *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8); |
| + *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2, |
| + 8); |
| buf = kzalloc(*len, GFP_KERNEL); |
| if (buf == NULL) |
| return buf; |
| |
| sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + |
| - sizeof(struct cifs_ace); |
| + 2 * sizeof(struct cifs_ace); |
| |
| buf->ccontext.DataOffset = cpu_to_le16(offsetof |
| (struct crt_sd_ctxt, sd)); |
| @@ -2232,8 +2233,12 @@ create_sd_buf(umode_t mode, unsigned int |
| /* 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); |
| + /* and one more ACE to allow access for authenticated users */ |
| + pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + |
| + (char *)buf)); |
| + acelen += setup_authusers_ACE(pace); |
| buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); |
| - buf->acl.AceCount = cpu_to_le16(1); |
| + buf->acl.AceCount = cpu_to_le16(2); |
| return buf; |
| } |
| |