ksmbd: fix slab out of bounds write in smb_inherit_dacl()
[ Upstream commit 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: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
1c701423bb
Коммит
aaf0a07d60
|
@ -1105,6 +1105,7 @@ pass:
|
||||||
struct smb_acl *pdacl;
|
struct smb_acl *pdacl;
|
||||||
struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
|
struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
|
||||||
int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
|
int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
|
||||||
|
int pntsd_alloc_size;
|
||||||
|
|
||||||
if (parent_pntsd->osidoffset) {
|
if (parent_pntsd->osidoffset) {
|
||||||
powner_sid = (struct smb_sid *)((char *)parent_pntsd +
|
powner_sid = (struct smb_sid *)((char *)parent_pntsd +
|
||||||
|
@ -1117,9 +1118,10 @@ pass:
|
||||||
pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
|
pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
|
pntsd_alloc_size = sizeof(struct smb_ntsd) + powner_sid_size +
|
||||||
pgroup_sid_size + sizeof(struct smb_acl) +
|
pgroup_sid_size + sizeof(struct smb_acl) + nt_size;
|
||||||
nt_size, GFP_KERNEL);
|
|
||||||
|
pntsd = kzalloc(pntsd_alloc_size, GFP_KERNEL);
|
||||||
if (!pntsd) {
|
if (!pntsd) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto free_aces_base;
|
goto free_aces_base;
|
||||||
|
@ -1134,6 +1136,27 @@ pass:
|
||||||
pntsd->gsidoffset = parent_pntsd->gsidoffset;
|
pntsd->gsidoffset = parent_pntsd->gsidoffset;
|
||||||
pntsd->dacloffset = parent_pntsd->dacloffset;
|
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) {
|
if (pntsd->osidoffset) {
|
||||||
struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
|
struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
|
||||||
le32_to_cpu(pntsd->osidoffset));
|
le32_to_cpu(pntsd->osidoffset));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче