* [PATCH net 0/1] net: ipv6: clear suppressed fib6 rule result
@ 2026-07-23 16:48 Ren Wei
2026-07-23 16:48 ` [PATCH net 1/1] " Ren Wei
0 siblings, 1 reply; 3+ messages in thread
From: Ren Wei @ 2026-07-23 16:48 UTC (permalink / raw)
To: netdev
Cc: dsahern, idosch, davem, edumazet, pabeni, horms, Jason, vega,
zhilinz, enjou1224z
From: Zhiling Zou <zhilinz@nebusec.ai>
Hi Linux kernel maintainers,
We found and validated a issue in net/ipv6/fib6_rules.c. The bug is
reachable by a non-root user via user and net namespace.
We've tested it, and it should not affect any other functionality.
We will provide detailed information about the bug
in this email, along with a PoC to trigger it.
---- details below ----
Bug details:
fib6_rule_suppress() drops a route that matches
suppress_prefixlength, but leaves res->rt6 pointing at the released
rt6_info.
If no later IPv6 rule replaces that result, fib6_rule_lookup() still
returns the stale dst because it only checks whether res.rt6 is
non-NULL. With a final suppressing main-table rule, an unprivileged
user can first observe the wrong lookup result with `ip -6 route get`,
then trigger an imbalanced dst_release() by creating an ip6tnl device
that reuses the stale route.
The attached change clears res->rt6 when a suppressing rule rejects the
route, so the lookup falls through to the null dst instead of reusing a
released route.
Reproducer:
chmod +x ./poc.sh
./poc.sh
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN poc.sh------
#!/bin/sh
set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin
panic_on_warn="$(cat /proc/sys/kernel/panic_on_warn)"
if [ "$panic_on_warn" != "1" ]; then
printf '%s\n' "warning: kernel.panic_on_warn=$panic_on_warn; the bug is still observable, but this setup may only WARN instead of panicking." >&2
fi
exec unshare -Urn /bin/sh -euxc '
ip link set lo up
ip link add dummy0 type dummy
ip link set dummy0 up
ip -6 addr add 2001:db8:1::1/64 dev dummy0 nodad
ip -6 rule del pref 32766
ip -6 rule add pref 32766 table main suppress_prefixlength 64
ip -6 route get 2001:db8:1::2
ip link add tun0 type ip6tnl local 2001:db8:1::1 remote 2001:db8:1::2 mode ip6ip6
'
------END poc.sh--------
----BEGIN crash log----
[ 28.263573] Kernel panic - not syncing: kernel: panic_on_warn set ...
[ 28.264178] CPU: 3 UID: 1028 PID: 853 Comm: ip Not tainted 6.12.95 #1
[ 28.264734] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 28.265729] Call Trace:
[ 28.265964] <TASK>
[ 28.266157] panic+0x352/0x3e0
[ 28.266435] ? rcuref_put_slowpath+0x67/0x70
[ 28.266817] check_panic_on_warn+0x44/0x60
[ 28.267191] __warn+0x91/0x120
[ 28.267462] ? rcuref_put_slowpath+0x67/0x70
[ 28.267841] report_bug+0x150/0x170
[ 28.268163] handle_bug+0x10a/0x170
[ 28.268472] exc_invalid_op+0x17/0x70
[ 28.268798] asm_exc_invalid_op+0x1a/0x20
[ 28.269160] RIP: 0010:rcuref_put_slowpath+0x67/0x70
[ 28.269589] Code: 31 c0 eb f0 80 3d 29 bf cf 02 00 74 0a c7 03 00 00 00 e0 31 c0 eb dd 48 c7 c7 7d 36 7e 83 c6 05 0f bf cf 02 01 e8 39 95 62 ff <0f> 0b eb df 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90
[ 28.271193] RSP: 0018:ffffc900011cf810 EFLAGS: 00010286
[ 28.271648] RAX: 0000000000000000 RBX: ffff888106388e00 RCX: 0000000000000027
[ 28.272293] RDX: ffff88813bda1a08 RSI: 0000000000000001 RDI: ffff88813bda1a00
[ 28.272908] RBP: ffffc900011cf858 R08: 0000000000000000 R09: 0000000000000003
[ 28.273523] R10: ffffc900011cf6b0 R11: ffffffff84583688 R12: ffff88810aecc000
[ 28.274148] R13: ffff88810bcd1000 R14: ffff88810aecc9c8 R15: 0000000000000000
[ 28.274758] dst_release+0x35/0x90
[ 28.275075] ip6_tnl_link_config+0x150/0x1c0
[ 28.275452] ip6_tnl_dev_init+0xdb/0x110
[ 28.275796] register_netdevice+0x159/0x840
[ 28.276169] ? srso_alias_return_thunk+0x5/0xfbef5
[ 28.276586] ? nla_memcpy+0x27/0x50
[ 28.276973] ip6_tnl_create2+0x38/0x170
[ 28.277311] ip6_tnl_newlink+0xa8/0x110
[ 28.277650] __rtnl_newlink+0x761/0x9d0
[ 28.278001] rtnl_newlink+0x47/0x70
[ 28.278295] rtnetlink_rcv_msg+0x2ca/0x440
[ 28.278689] ? ___slab_alloc+0x989/0xba0
[ 28.279058] ? kmalloc_reserve+0x93/0x100
[ 28.279441] ? __pfx_rtnetlink_rcv_msg+0x10/0x10
[ 28.279833] netlink_rcv_skb+0x58/0x110
[ 28.280138] netlink_unicast+0x25d/0x390
[ 28.280429] netlink_sendmsg+0x222/0x490
[ 28.280739] __sock_sendmsg+0x83/0x90
[ 28.281105] ____sys_sendmsg+0x28c/0x310
[ 28.281476] ? copy_msghdr_from_user+0x7d/0xc0
[ 28.281909] ___sys_sendmsg+0x9a/0xe0
[ 28.282254] ? __handle_mm_fault+0x5ed/0x860
[ 28.282662] ? __count_memcg_events+0x79/0x140
[ 28.283112] __sys_sendmsg+0x87/0xe0
[ 28.283459] do_syscall_64+0x58/0x120
[ 28.283815] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 28.284342] RIP: 0033:0x7d3d96dd8687
[ 28.284711] Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
[ 28.286534] RSP: 002b:00007ffcbfa96590 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
[ 28.287285] RAX: ffffffffffffffda RBX: 00007d3d96bab840 RCX: 00007d3d96dd8687
[ 28.288012] RDX: 0000000000000000 RSI: 00007ffcbfa96640 RDI: 0000000000000003
[ 28.288714] RBP: 00007ffcbfa96640 R08: 0000000000000000 R09: 0000000000000000
[ 28.289537] R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffcbfa9674c
[ 28.290421] R13: 00005bb13a7ca920 R14: 00005bb13a7ca020 R15: 0000000000000000
[ 28.291350] </TASK>
[ 28.292986] Kernel Offset: disabled
-----END crash log-----
Best regards,
Zhiling Zou
Zhiling Zou (1):
net: ipv6: clear suppressed fib6 rule result
net/ipv6/fib6_rules.c | 1 +
1 file changed, 1 insertion(+)
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH net 1/1] net: ipv6: clear suppressed fib6 rule result
2026-07-23 16:48 [PATCH net 0/1] net: ipv6: clear suppressed fib6 rule result Ren Wei
@ 2026-07-23 16:48 ` Ren Wei
2026-07-26 12:16 ` Ido Schimmel
0 siblings, 1 reply; 3+ messages in thread
From: Ren Wei @ 2026-07-23 16:48 UTC (permalink / raw)
To: netdev
Cc: dsahern, idosch, davem, edumazet, pabeni, horms, Jason, vega,
zhilinz, enjou1224z
From: Zhiling Zou <zhilinz@nebusec.ai>
fib6_rule_suppress() drops a suppressed route with ip6_rt_put_flags(),
but leaves res->rt6 pointing at the released rt6_info.
If no later rule supplies a replacement, fib6_rule_lookup() still sees
res.rt6 and returns that stale dst to its caller. A suppressing rule can
therefore leak a released route back to rt6_lookup(), and the next put
hits rcuref_put_slowpath() from dst_release().
Clear res->rt6 when suppressing the route so suppressed lookups fall
through to the null dst instead of reusing the released one.
Fixes: cdef485217d3 ("ipv6: fix memory leak in fib6_rule_suppress")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai>
Signed-off-by: Ren Wei <enjou1224z@gmail.com>
---
net/ipv6/fib6_rules.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index e1b2b4fa6e18..89ee3c969ca7 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -308,6 +308,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule,
suppress_route:
ip6_rt_put_flags(rt, flags);
+ res->rt6 = NULL;
return true;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net 1/1] net: ipv6: clear suppressed fib6 rule result
2026-07-23 16:48 ` [PATCH net 1/1] " Ren Wei
@ 2026-07-26 12:16 ` Ido Schimmel
0 siblings, 0 replies; 3+ messages in thread
From: Ido Schimmel @ 2026-07-26 12:16 UTC (permalink / raw)
To: Ren Wei
Cc: netdev, dsahern, davem, edumazet, pabeni, horms, Jason, vega,
zhilinz
On Fri, Jul 24, 2026 at 12:48:52AM +0800, Ren Wei wrote:
> From: Zhiling Zou <zhilinz@nebusec.ai>
>
> fib6_rule_suppress() drops a suppressed route with ip6_rt_put_flags(),
> but leaves res->rt6 pointing at the released rt6_info.
>
> If no later rule supplies a replacement, fib6_rule_lookup() still sees
> res.rt6 and returns that stale dst to its caller. A suppressing rule can
> therefore leak a released route back to rt6_lookup(), and the next put
> hits rcuref_put_slowpath() from dst_release().
>
> Clear res->rt6 when suppressing the route so suppressed lookups fall
> through to the null dst instead of reusing the released one.
>
> Fixes: cdef485217d3 ("ipv6: fix memory leak in fib6_rule_suppress")
Doesn't matter in practice given this commit was backported, but it
seems that the bug was introduced by commit 7764a45a8f1f ("fib_rules:
add .suppress operation").
> Cc: stable@vger.kernel.org
> Reported-by: Vega <vega@nebusec.ai>
> Assisted-by: Codex:gpt-5.4
> Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai>
> Signed-off-by: Ren Wei <enjou1224z@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
> net/ipv6/fib6_rules.c | 1 +
> 1 file changed, 1 insertion(+)
AFAICT, IPv4 doesn't suffer from this bug given that:
1. fib4_rule_suppress() only drops the reference from the FIB info when
FIB_LOOKUP_NOREF is not set and it is always set by fib_lookup().
2. Unlike fib6_rule_lookup(), __fib_lookup() doesn't ignore the return
value of fib_rules_lookup() and propagates it to the callers.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-26 12:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 16:48 [PATCH net 0/1] net: ipv6: clear suppressed fib6 rule result Ren Wei
2026-07-23 16:48 ` [PATCH net 1/1] " Ren Wei
2026-07-26 12:16 ` Ido Schimmel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.