xfrm: validate new SA's prefixlen using SA family when sel.family is unset
authorSabrina Dubroca <sd@queasysnail.net>
Tue, 1 Oct 2024 16:48:14 +0000 (18:48 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 7 Oct 2024 07:09:08 +0000 (09:09 +0200)
This expands the validation introduced in commit 07bf7908950a ("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: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/xfrm/xfrm_user.c

index 55f039e..8d06a37 100644 (file)
@@ -201,6 +201,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
 {
        int err;
        u8 sa_dir = attrs[XFRMA_SA_DIR] ? nla_get_u8(attrs[XFRMA_SA_DIR]) : 0;
+       u16 family = p->sel.family;
 
        err = -EINVAL;
        switch (p->family) {
@@ -221,7 +222,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;