From patchwork Fri Jul 19 06:43:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 1133913 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cdf9UHBK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45qhKn6nXLz9s7T for ; Fri, 19 Jul 2019 16:43:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725853AbfGSGnk (ORCPT ); Fri, 19 Jul 2019 02:43:40 -0400 Received: from mail-pl1-f173.google.com ([209.85.214.173]:44807 "EHLO mail-pl1-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725616AbfGSGnk (ORCPT ); Fri, 19 Jul 2019 02:43:40 -0400 Received: by mail-pl1-f173.google.com with SMTP id t14so15106157plr.11 for ; Thu, 18 Jul 2019 23:43:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=wUpTp6AtD2MSjysLZIpVuQJ8GCkcCI+SDwn1o/40S6I=; b=cdf9UHBKRmNsTsC6SrFvM6KDjgms9b5T8zLuwVhFTU1mQUAuBHvnpC8vzfNLt+aqX5 oAiv2WnhEKJmw5Rz4PmTb5Ww8r9opsVjgQZ4ZbncHSF05Zf+GkVEXjKkJXt9amoC5Tbk O8/JyCr3K7R5fLDGH+3F7X3YiOL0jxFA8zQETQcltpeVE3S7Oqq/OwQoCy6J08QPn6mN MJ8m29NDUp6CzJ/IUjeu2o5Hcw3WwFg8ffoeGhIj3zvf6mNmNtAnGU2/uQIQsRmS9nHj 6gHbGV2xA7LejyhVyMul0GYOhdyrEv902u44GPxOndqhfn00mWIZq8qd9Ec8MAuF24dF s5ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=wUpTp6AtD2MSjysLZIpVuQJ8GCkcCI+SDwn1o/40S6I=; b=ArSDWT0Rt4Ft82USBnj4yYgfoPF3G1ZO+b8SP3LTHzgQx4CervIuCLHO8sfKBaBEVI Hw0HbnTIeOi81yrHIc/BcAZYrmfLxM5ImzC8BHn5Nfa+KRUCqRLXI8JETTKoSpgeDpiL UUslskh65PJcq+xgtOWA4cp+5+tHQ45+FJecSmoSaPLsYZJt5BfMV/tr8upOt92AtPWW xooAewrERRSum4+ln753uTjqelqEf7g4lhopEcCnEBZrzLKHTdQThrzD5Zsn6J2dt/ZE XvkZAkJpDuMerbUH7TBvsOYo+Vw63VdXkO2apmNWRZtQDNC4raW8xzQzgoLR4UKWnO1B 1xpw== X-Gm-Message-State: APjAAAWT5watufmsIaerugLuyEkefP63N/6ubeTtqquCg8PiGNNPlr7k zy7iuSte7+Ve29ISBb2teVrb5kLsWSr7mYeQR0Y4jwfG0Y8= X-Google-Smtp-Source: APXvYqyfKrCzq+tAW1DSC4TumQUveGvc27el0r+xB/xC74f22ruV7zcFtbqkpr4TzPSksFFRH7LKpLjbgutEu4udI+A= X-Received: by 2002:a17:902:20b:: with SMTP id 11mr55728433plc.78.1563518618911; Thu, 18 Jul 2019 23:43:38 -0700 (PDT) MIME-Version: 1.0 From: Steve French Date: Fri, 19 Jul 2019 01:43:27 -0500 Message-ID: Subject: [PATCH][CIFS] Get mode bits on stat from special SID when requested on mount To: CIFS Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org When mounting with "modefromsid" retrieve mode bits from special SID (S-1-5-88-3) on stat. Subsequent patch will fix setattr (chmod) to save mode bits in S-1-5-88-3- Note that when an ACE matching S-1-5-88-3 is not found, we default the mode to an approximation based on the owner, group and everyone permissions (as with the "cifsacl" mount option). See See e.g. https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10) Below is an example of 3 files created (over NFS to Windows) with three different modes, and note that their permissions now display accurately: # stat /mnt-to-windows/file0777 File: /mnt-to-windows/file0777 Size: 0 Blocks: 0 IO Block: 1048576 regular empty file Device: 33h/51d Inode: 4785074604105433 Links: 1 Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2019-07-19 01:31:53.728517100 +0000 Modify: 2019-07-19 01:31:53.728517100 +0000 Change: 2019-07-19 01:36:40.588153100 +0000 Birth: - # stat /mnt-to-windows/file0400 File: /mnt-to-windows/file0400 Size: 0 Blocks: 0 IO Block: 1048576 regular empty file Device: 33h/51d Inode: 1970324836998972 Links: 1 Access: (0400/-r--------) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2019-07-19 01:31:55.760662400 +0000 Modify: 2019-07-19 01:31:55.760662400 +0000 Change: 2019-07-19 01:36:40.588153100 +0000 Birth: - # stat /mnt-to-windows/file3777 File: /mnt-to-windows/file3777 Size: 0 Blocks: 0 IO Block: 1048576 regular empty file Device: 33h/51d Inode: 1407374883577661 Links: 1 Access: (3777/-rwxrwsrwt) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2019-07-19 01:32:01.653725200 +0000 Modify: 2019-07-19 01:32:01.653725200 +0000 Change: 2019-07-19 01:36:40.588153100 +0000 From 6f86874c1d03eda5b6181064fde7b4bf0d2e37f4 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 19 Jul 2019 06:30:07 +0000 Subject: [PATCH] cifs: get mode bits from special sid on stat When mounting with "modefromsid" retrieve mode bits from special SID (S-1-5-88-3) on stat. Subsequent patch will fix setattr (chmod) to save mode bits in S-1-5-88-3- Note that when an ACE matching S-1-5-88-3 is not found, we default the mode to an approximation based on the owner, group and everyone permissions (as with the "cifsacl" mount option). See See e.g. https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10) Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 37 ++++++++++++++++++++++++++----------- fs/cifs/cifsproto.h | 1 + fs/cifs/inode.c | 13 +++++++++++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1d377b7f2860..2a14748b8e09 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -701,10 +701,9 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) } #endif - static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, - struct cifs_fattr *fattr) + struct cifs_fattr *fattr, bool mode_from_special_sid) { int i; int num_aces = 0; @@ -757,22 +756,34 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, #ifdef CONFIG_CIFS_DEBUG2 dump_ace(ppace[i], end_of_acl); #endif - if (compare_sids(&(ppace[i]->sid), pownersid) == 0) + if (mode_from_special_sid && + (compare_sids(&(ppace[i]->sid), + &sid_unix_NFS_mode) == 0)) { + /* + * Full permissions are: + * 07777 = S_ISUID | S_ISGID | S_ISVTX | + * S_IRWXU | S_IRWXG | S_IRWXO + */ + fattr->cf_mode &= ~07777; + fattr->cf_mode |= + le32_to_cpu(ppace[i]->sid.sub_auth[2]); + break; + } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, &fattr->cf_mode, &user_mask); - if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) + else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, &fattr->cf_mode, &group_mask); - if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) + else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, &fattr->cf_mode, &other_mask); - if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) + else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, &fattr->cf_mode, @@ -851,7 +862,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) /* Convert CIFS ACL to POSIX form */ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, - struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) + struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, + bool get_mode_from_special_sid) { int rc = 0; struct cifs_sid *owner_sid_ptr, *group_sid_ptr; @@ -900,7 +912,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, if (dacloffset) parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, - group_sid_ptr, fattr); + group_sid_ptr, fattr, get_mode_from_special_sid); else cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ @@ -1128,8 +1140,8 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - struct inode *inode, const char *path, - const struct cifs_fid *pfid) + struct inode *inode, bool mode_from_special_sid, + const char *path, const struct cifs_fid *pfid) { struct cifs_ntsd *pntsd = NULL; u32 acllen = 0; @@ -1156,8 +1168,11 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, if (IS_ERR(pntsd)) { rc = PTR_ERR(pntsd); cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); + } else if (mode_from_special_sid) { + rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); } else { - rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); + /* get approximated mode from ACL */ + rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false); kfree(pntsd); if (rc) cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e23234207fc2..2def872ea727 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -197,6 +197,7 @@ extern int cifs_rename_pending_delete(const char *full_path, const unsigned int xid); extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, + bool get_mode_from_special_sid, const char *path, const struct cifs_fid *pfid); extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, kuid_t, kgid_t); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 56ca4b8ccaba..c1e620ebcf7c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -893,8 +893,17 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, } /* fill in 0777 bits from ACL */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) { + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true, + full_path, fid); + if (rc) { + cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n", + __func__, rc); + goto cgii_exit; + } + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false, + full_path, fid); if (rc) { cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", __func__, rc); -- 2.20.1