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

[ Upstream commit 3f0ab59e65 ]

This expands the validation introduced in commit 07bf790895 ("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: syzbot+cc39f136925517aed571@syzkaller.appspotmail.com
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Sabrina Dubroca 2024-10-01 18:48:14 +02:00 committed by Greg Kroah-Hartman
parent 354b3847ea
commit bce1afaa21

View File

@ -176,6 +176,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
struct netlink_ext_ack *extack)
{
int err;
u16 family = p->sel.family;
err = -EINVAL;
switch (p->family) {
@ -196,7 +197,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;