Skip to content

Commit 20eb528

Browse files
nszeteiopsiff
authored andcommitted
ksmbd: fix overflow in dacloffset bounds check
stable inclusion from stable-v6.15-rc1 commit beff0bc category: bugfix CVE: CVE-2025-22039 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=beff0bc9d69bc8e733f9bca28e2d3df5b3e10e42 -------------------------------- The dacloffset field was originally typed as int and used in an unchecked addition, which could overflow and bypass the existing bounds check in both smb_check_perm_dacl() and smb_inherit_dacl(). This could result in out-of-bounds memory access and a kernel crash when dereferencing the DACL pointer. This patch converts dacloffset to unsigned int and uses check_add_overflow() to validate access to the DACL. Cc: stable@vger.kernel.org Signed-off-by: Norbert Szetei <norbert@doyensec.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit beff0bc) Signed-off-by: Wentao Guan <guanwentao@uniontech.com> Conflicts: fs/smb/server/smbacl.c
1 parent 20d3ae7 commit 20eb528

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

fs/smb/server/smbacl.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,16 +1031,21 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
10311031
struct dentry *parent = path->dentry->d_parent;
10321032
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
10331033
int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size;
1034-
int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
1034+
int rc = 0, num_aces, pntsd_type, pntsd_size, acl_len, aces_size;
1035+
unsigned int dacloffset;
1036+
size_t dacl_struct_end;
10351037
char *aces_base;
10361038
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
10371039

10381040
pntsd_size = ksmbd_vfs_get_sd_xattr(conn, idmap,
10391041
parent, &parent_pntsd);
10401042
if (pntsd_size <= 0)
10411043
return -ENOENT;
1044+
10421045
dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
1043-
if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) {
1046+
if (!dacloffset ||
1047+
check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) ||
1048+
dacl_struct_end > (size_t)pntsd_size) {
10441049
rc = -EINVAL;
10451050
goto free_parent_pntsd;
10461051
}
@@ -1243,7 +1248,9 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
12431248
struct smb_ntsd *pntsd = NULL;
12441249
struct smb_acl *pdacl;
12451250
struct posix_acl *posix_acls;
1246-
int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset;
1251+
int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size;
1252+
unsigned int dacl_offset;
1253+
size_t dacl_struct_end;
12471254
struct smb_sid sid;
12481255
int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE);
12491256
struct smb_ace *ace;
@@ -1262,7 +1269,8 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
12621269

12631270
dacl_offset = le32_to_cpu(pntsd->dacloffset);
12641271
if (!dacl_offset ||
1265-
(dacl_offset + sizeof(struct smb_acl) > pntsd_size))
1272+
check_add_overflow(dacl_offset, sizeof(struct smb_acl), &dacl_struct_end) ||
1273+
dacl_struct_end > (size_t)pntsd_size)
12661274
goto err_out;
12671275

12681276
pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));

0 commit comments

Comments
 (0)