]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smb/client: fix security flag calculation when setting security descriptors
authorRalph Boehme <slow@samba.org>
Sat, 20 Jun 2026 07:12:42 +0000 (09:12 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 24 Jun 2026 15:33:41 +0000 (10:33 -0500)
In id_mode_to_cifs_acl(), aclflag was initialized to CIFS_ACL_DACL by default.
This forced the client to request setting the DACL even when only an ownership
(chown) or group (chgrp) change was being performed.

Let build_sec_desc() do the proper flag calculation by initializing aclflag
to 0. build_sec_desc() sets the appropriate bits (CIFS_ACL_OWNER, CIFS_ACL_GROUP,
or CIFS_ACL_DACL) depending on what actually changed. During ownership transfer,
CIFS_ACL_DACL is only set if replace_sids_and_copy_aces() actually replaces the
SIDs inside any of the DACL's ACEs.

If build_sec_desc() results in aclflag being 0 (meaning no changes were mapped),
exit early to avoid sending an empty security descriptor update to the server.

Signed-off-by: Ralph Boehme <slow@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsacl.c

index 5bbf737363581cc04cf5cdd6140f1b1fa46cba59..07cf0e5782337d9d26801db4a8929927d749ea3b 100644 (file)
@@ -1185,7 +1185,8 @@ set_size:
 
 static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *pndacl,
                struct smb_sid *pownersid, struct smb_sid *pgrpsid,
-               struct smb_sid *pnownersid, struct smb_sid *pngrpsid)
+               struct smb_sid *pnownersid, struct smb_sid *pngrpsid,
+               int *aclflag)
 {
        int i;
        u16 size = 0;
@@ -1209,12 +1210,15 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p
                pntace = (struct smb_ace *) (acl_base + size);
                pnntace = (struct smb_ace *) (nacl_base + nsize);
 
-               if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
+               if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0) {
                        ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
-               else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0)
+                       *aclflag |= CIFS_ACL_DACL;
+               } else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0) {
                        ace_size = cifs_copy_ace(pnntace, pntace, pngrpsid);
-               else
+                       *aclflag |= CIFS_ACL_DACL;
+               } else {
                        ace_size = cifs_copy_ace(pnntace, pntace, NULL);
+               }
 
                size += le16_to_cpu(pntace->size);
                nsize += ace_size;
@@ -1521,7 +1525,8 @@ static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
                        /* Replace ACEs for old owner with new one */
                        size = replace_sids_and_copy_aces(dacl_ptr, ndacl_ptr,
                                        owner_sid_ptr, group_sid_ptr,
-                                       nowner_sid_ptr, ngroup_sid_ptr);
+                                       nowner_sid_ptr, ngroup_sid_ptr,
+                                       aclflag);
                        ndacl_ptr->size = cpu_to_le16(size);
                }
 
@@ -1738,7 +1743,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
                        kuid_t uid, kgid_t gid)
 {
        int rc = 0;
-       int aclflag = CIFS_ACL_DACL; /* default flag to set */
+       int aclflag = 0;
        __u32 secdesclen = 0;
        __u32 nsecdesclen = 0;
        __u32 dacloffset = 0;
@@ -1837,6 +1842,11 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
        if (rc != 0)
                goto id_mode_to_cifs_acl_exit;
 
+       if (aclflag == 0) {
+               cifs_dbg(FYI, "set_cifs_acl aclflag=0, no change mapped\n");
+               goto id_mode_to_cifs_acl_exit;
+       }
+
        if (ops->set_acl == NULL) {
                rc = -EOPNOTSUPP;
                goto id_mode_to_cifs_acl_exit;