Commit dedbf400 authored by Yang Xiongwei's avatar Yang Xiongwei Committed by Wang Zhaolong
Browse files

ksmbd: fix slab out of bounds write in smb_inherit_dacl()

mainline inclusion
from mainline-v6.7-rc1
commit eebff19acaa35820cb09ce2ccb3d21bee2156ffb
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9R4LC
CVE: CVE-2023-52755

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=eebff19acaa35820cb09ce2ccb3d21bee2156ffb



--------------------------------

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: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Conflicts:
	fs/smb/server/smbacl.c
	fs/ksmbd/smbacl.c
[lc:file path is not same]
Signed-off-by: default avatarXiongWei Yang <yangxiongwei6@huawei.com>
Signed-off-by: default avatarWang Zhaolong <wangzhaolong1@huawei.com>
parent f4b00a3e
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -1098,6 +1098,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 +
@@ -1110,9 +1111,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;
@@ -1127,6 +1129,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));