Skip to content

Commit

Permalink
ksmbd: fix slab out of bounds write in smb_inherit_dacl()
Browse files Browse the repository at this point in the history
commit eebff19 upstream.

slab out-of-bounds write is caused by that offsets is bigger than pntsd
allocation size. This patch add the check to validate 3 offsets using
allocation size.

Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22271
Cc: stable@vger.kernel.org
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>
  • Loading branch information
namjaejeon authored and gregkh committed Nov 28, 2023
1 parent 8434e02 commit 09d9d8b
Showing 1 changed file with 26 additions and 3 deletions.
29 changes: 26 additions & 3 deletions fs/smb/server/smbacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
struct smb_acl *pdacl;
struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
int pntsd_alloc_size;

if (parent_pntsd->osidoffset) {
powner_sid = (struct smb_sid *)((char *)parent_pntsd +
Expand All @@ -1119,9 +1120,10 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
}

pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
pgroup_sid_size + sizeof(struct smb_acl) +
nt_size, GFP_KERNEL);
pntsd_alloc_size = sizeof(struct smb_ntsd) + powner_sid_size +
pgroup_sid_size + sizeof(struct smb_acl) + nt_size;

pntsd = kzalloc(pntsd_alloc_size, GFP_KERNEL);
if (!pntsd) {
rc = -ENOMEM;
goto free_aces_base;
Expand All @@ -1136,6 +1138,27 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
pntsd->gsidoffset = parent_pntsd->gsidoffset;
pntsd->dacloffset = parent_pntsd->dacloffset;

if ((u64)le32_to_cpu(pntsd->osidoffset) + powner_sid_size >
pntsd_alloc_size) {
rc = -EINVAL;
kfree(pntsd);
goto free_aces_base;
}

if ((u64)le32_to_cpu(pntsd->gsidoffset) + pgroup_sid_size >
pntsd_alloc_size) {
rc = -EINVAL;
kfree(pntsd);
goto free_aces_base;
}

if ((u64)le32_to_cpu(pntsd->dacloffset) + sizeof(struct smb_acl) + nt_size >
pntsd_alloc_size) {
rc = -EINVAL;
kfree(pntsd);
goto free_aces_base;
}

if (pntsd->osidoffset) {
struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
Expand Down

0 comments on commit 09d9d8b

Please sign in to comment.