]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: validate SID namespace before mapping IDs
authorNamjae Jeon <linkinjeon@kernel.org>
Wed, 1 Jul 2026 13:58:35 +0000 (22:58 +0900)
committerSteve French <stfrench@microsoft.com>
Mon, 6 Jul 2026 12:55:41 +0000 (07:55 -0500)
sid_to_id() currently treats the last subauthority of any owner or group
SID as a Unix uid or gid. For example, this maps Everyone (S-1-1-0) to
uid 0 and BUILTIN\Users (S-1-5-32-545) to gid 545.

When an SMB2 CREATE security descriptor contains those SIDs, ksmbd
attempts to change the newly created file to the bogus Unix ownership.
notify_change() then returns -EPERM, which makes smb2.create.aclfile fail
with NT_STATUS_SHARING_VIOLATION.

Validate the SID prefix before extracting its RID. Only server-domain
owner SIDs and S-1-22-2 Unix group SIDs have local ID representations.
Treat other valid Windows SIDs as unmapped so their original values can
still be preserved in the NT ACL xattr.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smbacl.c

index 9c59c8f73b6675ef73c8f69daf0d279d22d61142..67b39b4d218cc93abd1de437bf152923bbd8c0ce 100644 (file)
@@ -258,6 +258,7 @@ static int sid_to_id(struct mnt_idmap *idmap,
                     struct smb_sid *psid, uint sidtype,
                     struct smb_fattr *fattr)
 {
+       const struct smb_sid *sid_prefix;
        int rc = -EINVAL;
 
        /*
@@ -279,6 +280,12 @@ static int sid_to_id(struct mnt_idmap *idmap,
                kuid_t uid;
                uid_t id;
 
+               /* Only the server domain RID has a local uid representation. */
+               sid_prefix = &server_conf.domain_sid;
+               if (psid->num_subauth != sid_prefix->num_subauth + 1 ||
+                   compare_sids(psid, sid_prefix))
+                       return -EINVAL;
+
                id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
                uid = KUIDT_INIT(id);
                uid = from_vfsuid(idmap, &init_user_ns, VFSUIDT_INIT(uid));
@@ -290,6 +297,12 @@ static int sid_to_id(struct mnt_idmap *idmap,
                kgid_t gid;
                gid_t id;
 
+               /* Local gids are represented by S-1-22-2-<gid>. */
+               sid_prefix = &sid_unix_groups;
+               if (psid->num_subauth != sid_prefix->num_subauth + 1 ||
+                   compare_sids(psid, sid_prefix))
+                       return -EINVAL;
+
                id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
                gid = KGIDT_INIT(id);
                gid = from_vfsgid(idmap, &init_user_ns, VFSGIDT_INIT(gid));
@@ -900,9 +913,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
 
                rc = sid_to_id(idmap, owner_sid_ptr, SIDOWNER, fattr);
                if (rc) {
-                       pr_err("%s: Error %d mapping Owner SID to uid\n",
-                              __func__, rc);
+                       ksmbd_debug(SMB, "Owner SID has no Unix uid mapping\n");
                        owner_sid_ptr = NULL;
+                       rc = 0;
                }
        }
 
@@ -918,9 +931,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
                }
                rc = sid_to_id(idmap, group_sid_ptr, SIDUNIX_GROUP, fattr);
                if (rc) {
-                       pr_err("%s: Error %d mapping Group SID to gid\n",
-                              __func__, rc);
+                       ksmbd_debug(SMB, "Group SID has no Unix gid mapping\n");
                        group_sid_ptr = NULL;
+                       rc = 0;
                }
        }