diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2024-10-01 18:48:14 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-11-01 01:58:34 +0100 |
commit | 7d9868180bd1e4cf37e7c5067362658971162366 (patch) | |
tree | 88e260b798656c2c041b8b57bd5541c2dbdc0c9e | |
parent | 7a26cb660775067a4d7da6ca48e024a8543bf848 (diff) | |
download | linux-rpi-7d9868180bd1e4cf37e7c5067362658971162366.tar.gz linux-rpi-7d9868180bd1e4cf37e7c5067362658971162366.tar.bz2 linux-rpi-7d9868180bd1e4cf37e7c5067362658971162366.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.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 35b775cf233c..1d91b42e7997 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; |