Commit 659612e1 authored by Sabrina Dubroca's avatar Sabrina Dubroca Committed by Dong Chenchen
Browse files

xfrm: validate new SA's prefixlen using SA family when sel.family is unset

stable inclusion
from stable-v4.19.323
commit f31398570acf0f0804c644006f7bfa9067106b0a
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB2SWP
CVE: CVE-2024-50142

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



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

[ Upstream commit 3f0ab59e6537c6a8f9e1b355b48f9c05a76e8563 ]

This expands the validation introduced in commit 07bf7908 ("xfrm:
Validate address prefix lengths in the xfrm selector.")

syzbot created an SA with
    usersa.sel.family = AF_UNSPEC
    usersa.sel.prefixlen_s = 128
    usersa.family = AF_INET

Because of the AF_UNSPEC selector, verify_newsa_info doesn't put
limits on prefixlen_{s,d}. But then copy_from_user_state sets
x->sel.family to usersa.family (AF_INET). Do the same conversion in
verify_newsa_info before validating prefixlen_{s,d}, since that's how
prefixlen is going to be used later on.

Reported-by: default avatar <syzbot+cc39f136925517aed571@syzkaller.appspotmail.com>
Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: default avatarAntony Antony <antony.antony@secunet.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarDong Chenchen <dongchenchen2@huawei.com>
parent 21eb7b92
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
			     struct nlattr **attrs)
{
	int err;
	u16 family = p->sel.family;

	err = -EINVAL;
	switch (p->family) {
@@ -166,7 +167,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
		goto out;
	}

	switch (p->sel.family) {
	if (!family && !(p->flags & XFRM_STATE_AF_UNSPEC))
		family = p->family;

	switch (family) {
	case AF_UNSPEC:
		break;