]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Mar 2025 12:01:51 +0000 (13:01 +0100)
commit d6e13e19063db24f94b690159d0633aaf72a0f03 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/smb/server/smbacl.c

index 1c9775f1efa56d2feb141669a65d36d9230238c3..da8ed72f335d9949c65225a149c41fae4c15879c 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);
        }