summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSabrina Dubroca <sd@queasysnail.net>2024-10-01 18:48:14 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-11-01 01:56:07 +0100
commitbce1afaa212ec380bf971614f70909a27882b862 (patch)
treee1af26eda03a2ea5b3c77ee1be18fae293d7cd47
parent354b3847ead1bc41a66df8f4baa9fd12688e1a4e (diff)
downloadlinux-stable-bce1afaa212ec380bf971614f70909a27882b862.tar.gz
linux-stable-bce1afaa212ec380bf971614f70909a27882b862.tar.bz2
linux-stable-bce1afaa212ec380bf971614f70909a27882b862.zip
xfrm: validate new SA's prefixlen using SA family when sel.family is unset
[ Upstream commit 3f0ab59e6537c6a8f9e1b355b48f9c05a76e8563 ] 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> Signed-off-by: Antony Antony <antony.antony@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--net/xfrm/xfrm_user.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 442b1271057a..2f6e0513dee5 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -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;