]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
cifs: Fix getting and setting SACLs over SMB1
authorPali Rohár <pali@kernel.org>
Mon, 14 Oct 2024 11:43:23 +0000 (13:43 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 29 Jan 2025 23:09:34 +0000 (17:09 -0600)
SMB1 callback get_cifs_acl_by_fid() currently ignores its last argument and
therefore ignores request for SACL_SECINFO. Fix this issue by correctly
propagating info argument from get_cifs_acl() and get_cifs_acl_by_fid() to
CIFSSMBGetCIFSACL() function and pass SACL_SECINFO when requested.

For accessing SACLs it is needed to open object with SYSTEM_SECURITY
access. Pass this flag when trying to get or set SACLs.

Same logic is in the SMB2+ code path.

This change fixes getting and setting of "system.cifs_ntsd_full" and
"system.smb3_ntsd_full" xattrs over SMB1 as currently it silentely ignored
SACL part of passed xattr buffer.

Fixes: 3970acf7ddb9 ("SMB3: Add support for getting and setting SACLs")
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsacl.c
fs/smb/client/cifsproto.h
fs/smb/client/cifssmb.c

index ba79aa2107cc9f5b5fa628e9b9998d04e78c8bc1..699a3f76d083460263845e80fcfb366148d05e4a 100644 (file)
@@ -1395,7 +1395,7 @@ chown_chgrp_exit:
 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
                                      const struct cifs_fid *cifsfid, u32 *pacllen,
-                                     u32 __maybe_unused unused)
+                                     u32 info)
 {
        struct smb_ntsd *pntsd = NULL;
        unsigned int xid;
@@ -1407,7 +1407,7 @@ struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 
        xid = get_xid();
        rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
-                               pacllen);
+                               pacllen, info);
        free_xid(xid);
 
        cifs_put_tlink(tlink);
@@ -1419,7 +1419,7 @@ struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 }
 
 static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
-               const char *path, u32 *pacllen)
+               const char *path, u32 *pacllen, u32 info)
 {
        struct smb_ntsd *pntsd = NULL;
        int oplock = 0;
@@ -1446,9 +1446,12 @@ static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
                .fid = &fid,
        };
 
+       if (info & SACL_SECINFO)
+               oparms.desired_access |= SYSTEM_SECURITY;
+
        rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (!rc) {
-               rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
+               rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen, info);
                CIFSSMBClose(xid, tcon, fid.netfid);
        }
 
@@ -1472,7 +1475,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
        if (inode)
                open_file = find_readable_file(CIFS_I(inode), true);
        if (!open_file)
-               return get_cifs_acl_by_path(cifs_sb, path, pacllen);
+               return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);
 
        pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
        cifsFileInfo_put(open_file);
@@ -1485,7 +1488,7 @@ int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
 {
        int oplock = 0;
        unsigned int xid;
-       int rc, access_flags;
+       int rc, access_flags = 0;
        struct cifs_tcon *tcon;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@@ -1498,10 +1501,12 @@ int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
        tcon = tlink_tcon(tlink);
        xid = get_xid();
 
-       if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
-               access_flags = WRITE_OWNER;
-       else
-               access_flags = WRITE_DAC;
+       if (aclflag & CIFS_ACL_OWNER || aclflag & CIFS_ACL_GROUP)
+               access_flags |= WRITE_OWNER;
+       if (aclflag & CIFS_ACL_SACL)
+               access_flags |= SYSTEM_SECURITY;
+       if (aclflag & CIFS_ACL_DACL)
+               access_flags |= WRITE_DAC;
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
index 223e5e231f428e8757db5e23fd3558e37a235536..fcc9da838b70f8144b5118deed1c2fdfe16165fe 100644 (file)
@@ -557,7 +557,7 @@ extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
                const struct nls_table *nls_codepage,
                struct cifs_sb_info *cifs_sb);
 extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
-                       __u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen);
+                       __u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen, __u32 info);
 extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
                        struct smb_ntsd *pntsd, __u32 len, int aclflag);
 extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
index 7f1cacc89dbb0febf28e751e4b7c0f1ef6dee9e7..3feaa0f6816999d9d3e0d89abd1ca011c34f5bea 100644 (file)
@@ -3369,7 +3369,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
-                 struct smb_ntsd **acl_inf, __u32 *pbuflen)
+                 struct smb_ntsd **acl_inf, __u32 *pbuflen, __u32 info)
 {
        int rc = 0;
        int buf_type = 0;
@@ -3392,7 +3392,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
        pSMB->MaxSetupCount = 0;
        pSMB->Fid = fid; /* file handle always le */
        pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
-                                    CIFS_ACL_DACL);
+                                    CIFS_ACL_DACL | info);
        pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
        inc_rfc1001_len(pSMB, 11);
        iov[0].iov_base = (char *)pSMB;