]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
ksmbd: fix out-of-bounds in parse_sec_desc()
authorNamjae Jeon <linkinjeon@kernel.org>
Tue, 18 Feb 2025 13:49:50 +0000 (22:49 +0900)
committerSteve French <stfrench@microsoft.com>
Mon, 3 Mar 2025 04:50:53 +0000 (22:50 -0600)
If osidoffset, gsidoffset and dacloffset could be greater than smb_ntsd
struct size. If it is smaller, It could cause slab-out-of-bounds.
And when validating sid, It need to check it included subauth array size.

Cc: stable@vger.kernel.org
Reported-by: Norbert Szetei <norbert@doyensec.com>
Tested-by: Norbert Szetei <norbert@doyensec.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smbacl.c

index d39d3e553366da73d50567d0ca3ebabe3c5097e2..89415b02dd649a566ea5031d364a2ea5d6c81467 100644 (file)
@@ -807,6 +807,13 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl)
                return -EINVAL;
        }
 
+       if (!psid->num_subauth)
+               return 0;
+
+       if (psid->num_subauth > SID_MAX_SUB_AUTHORITIES ||
+           end_of_acl < (char *)psid + 8 + sizeof(__le32) * psid->num_subauth)
+               return -EINVAL;
+
        return 0;
 }
 
@@ -848,6 +855,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
        pntsd->type = cpu_to_le16(DACL_PRESENT);
 
        if (pntsd->osidoffset) {
+               if (le32_to_cpu(pntsd->osidoffset) < sizeof(struct smb_ntsd))
+                       return -EINVAL;
+
                rc = parse_sid(owner_sid_ptr, end_of_acl);
                if (rc) {
                        pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
@@ -863,6 +873,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
        }
 
        if (pntsd->gsidoffset) {
+               if (le32_to_cpu(pntsd->gsidoffset) < sizeof(struct smb_ntsd))
+                       return -EINVAL;
+
                rc = parse_sid(group_sid_ptr, end_of_acl);
                if (rc) {
                        pr_err("%s: Error %d mapping Owner SID to gid\n",
@@ -884,6 +897,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
                pntsd->type |= cpu_to_le16(DACL_PROTECTED);
 
        if (dacloffset) {
+               if (dacloffset < sizeof(struct smb_ntsd))
+                       return -EINVAL;
+
                parse_dacl(idmap, dacl_ptr, end_of_acl,
                           owner_sid_ptr, group_sid_ptr, fattr);
        }