net: fib: Fix two use-after-free in drivers during RCU dump.
Subsystems (3)
cover net: fib: Fix two use-after-free in drivers during RCU dump.
syzbot reported fib_info UAF in netdevsim, and the same bug exists in rocker and mlxsw.
Patch 1 fixes it, and Patch 2 fixes the same type of bug of fib_rule.
Kuniyuki Iwashima (2):
ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
net: fib_rules: Don't dump dying fib_rule in fib_rules_dump().
include/net/fib_rules.h | 5 +++++ include/net/ip_fib.h | 5 +++++ net/core/fib_rules.c | 6 +++++- net/ipv4/fib_trie.c | 4 ++++ 4 files changed, 19 insertions(+), 1 deletion(-)
Signature · 1 line
2.54.0.1099.g489fc7bff1-goog
PATCH 1/2 ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
syzbot reported use-after-free in nsim_fib4_prepare_event(). [0]
The problem is that the following functions call fib_info_hold() / refcount_inc() while dumping fib_info under RCU, which is unsafe.
* mlxsw_sp_router_fib4_event()
* rocker_router_fib_event()
* nsim_fib4_prepare_event()
refcount_inc_not_zero() must be used, but it would be too late there.
Let's guarantee the lifetime of fib_info in fib_leaf_notify().
Note that IPv6 does not need the corresponding change since fib6_table_dump() holds fib6_table.tb6_lock.
[0]:refcount_t: addition on 0; use-after-free.
WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25, CPU#0: kworker/u8:15/3420
Modules linked in:
CPU: 0 UID: 0 PID: 3420 Comm: kworker/u8:15 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
Workqueue: netns cleanup_net
RIP: 0010:refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25
Code: eb 66 85 db 74 3e 83 fb 01 75 4c e8 1b f1 22 fd 48 8d 3d 84 cb f1 0a 67 48 0f b9 3a eb 4a e8 08 f1 22 fd 48 8d 3d 81 cb f1 0a <67> 48 0f b9 3a eb 37 e8 f5 f0 22 fd 48 8d 3d 7e cb f1 0a 67 48 0f
RSP: 0018:ffffc9000f2c7270 EFLAGS: 00010293
RAX: ffffffff84a18858 RBX: 0000000000000002 RCX: ffff888032ff9ec0
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff8f9353e0
RBP: 0000000000000000 R08: ffff888032ff9ec0 R09: 0000000000000005
R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880570cc000
R13: dffffc0000000000 R14: ffff88802b40563c R15: ffff8880570cc000
FS: 0000000000000000(0000) GS:ffff888126173000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fb1f4d5d000 CR3: 000000006072a000 CR4: 00000000003526f0
Call Trace:
<TASK>
__refcount_add include/linux/refcount.h:-1 [inline]
__refcount_inc include/linux/refcount.h:366 [inline]
refcount_inc include/linux/refcount.h:383 [inline]
fib_info_hold include/net/ip_fib.h:629 [inline]
nsim_fib4_prepare_event drivers/net/netdevsim/fib.c:930 [inline]
nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1000 [inline]
nsim_fib_event_nb+0x1055/0x1240 drivers/net/netdevsim/fib.c:1043
call_fib_notifier+0x45/0x80 net/core/fib_notifier.c:25
call_fib_entry_notifier net/ipv4/fib_trie.c:90 [inline]
fib_leaf_notify net/ipv4/fib_trie.c:2176 [inline]
fib_table_notify net/ipv4/fib_trie.c:2194 [inline]
fib_notify+0x36b/0x5e0 net/ipv4/fib_trie.c:2217
fib_net_dump net/core/fib_notifier.c:70 [inline]
register_fib_notifier+0x184/0x360 net/core/fib_notifier.c:108
nsim_fib_create+0x85d/0x9f0 drivers/net/netdevsim/fib.c:1596
nsim_dev_reload_create drivers/net/netdevsim/dev.c:1604 [inline]
nsim_dev_reload_up+0x374/0x7c0 drivers/net/netdevsim/dev.c:1058
devlink_reload+0x501/0x8d0 net/devlink/dev.c:475
devlink_pernet_pre_exit+0x1ff/0x420 net/devlink/core.c:558
ops_pre_exit_list net/core/net_namespace.c:161 [inline]
ops_undo_list+0x187/0x940 net/core/net_namespace.c:234
cleanup_net+0x56e/0x800 net/core/net_namespace.c:702
process_one_work kernel/workqueue.c:3314 [inline]
process_scheduled_works+0xb5d/0x1860 kernel/workqueue.c:3397
worker_thread+0xa53/0xfc0 kernel/workqueue.c:3478
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>--- include/net/ip_fib.h | 5 +++++ net/ipv4/fib_trie.c | 4 ++++ 2 files changed, 9 insertions(+)
include/net/ip_fib.h +5 -0
@@ -629,6 +629,11 @@ static inline void fib_info_hold(struct fib_info *fi)refcount_inc (&fi->fib_clntref); } +static inline bool fib_info_hold_safe (struct fib_info *fi) +{ +return refcount_inc_not_zero (&fi->fib_clntref); +} +static inline void fib_info_put (struct fib_info *fi) {if (refcount_dec_and_test (&fi->fib_clntref))
net/ipv4/fib_trie.c +4 -0
@@ -2172,10 +2172,14 @@ static int fib_leaf_notify(struct key_vector *l, struct fib_table *tb,if (fa->fa_slen == last_slen)continue ; +if (!fib_info_hold_safe (fa->fa_info)) +continue ; + last_slen = fa->fa_slen; err =call_fib_entry_notifier (nb,FIB_EVENT_ENTRY_REPLACE , l->key,KEYLENGTH - fa->fa_slen, fa, extack); +fib_info_put (fa->fa_info);if (err)return err; }
Signature · 1 line
2.54.0.1099.g489fc7bff1-goog
Re: [PATCH v1 net 1/2] ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
Quoted 16 lines · Kuniyuki Iwashima
syzbot reported use-after-free in
nsim_fib4_prepare_event(). [0]The problem is that the following functions call
fib_info_hold()/refcount_inc()while dumpingfib_infounder RCU, which is unsafe.*
mlxsw_sp_router_fib4_event()
*rocker_router_fib_event()
*nsim_fib4_prepare_event()
refcount_inc_not_zero()must be used, but it would be too late there.Let's guarantee the lifetime of
fib_infoinfib_leaf_notify().Note that IPv6 does not need the corresponding change since
fib6_table_dump()holds fib6_table.tb6_lock.
[...]
Quoted 5 lines
Fixes 0ae3eb7b4611 ("netdevsim: fib: Perform the route programming in a non-atomic context")Fixes c3852ef7f2f8 ("ipv4: fib: Replay events when registering FIB notifier")Reported-by [email protected]Signed-off-by Kuniyuki Iwashima <[email protected]>
Thanks!
Re: [PATCH v1 net 1/2] ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
In reply to Kuniyuki IwashimaQuoted 72 lines · Kuniyuki Iwashima
syzbot reported use-after-free in
nsim_fib4_prepare_event(). [0]The problem is that the following functions call
fib_info_hold()/refcount_inc()while dumpingfib_infounder RCU, which is unsafe.*
mlxsw_sp_router_fib4_event()
*rocker_router_fib_event()
*nsim_fib4_prepare_event()
refcount_inc_not_zero()must be used, but it would be too late there.Let's guarantee the lifetime of
fib_infoinfib_leaf_notify().Note that IPv6 does not need the corresponding change since
fib6_table_dump()holds fib6_table.tb6_lock.[0]:
refcount_t: addition on 0; use-after-free.WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25, CPU#0: kworker/u8:15/3420 Modules linked in: CPU: 0 UID: 0 PID: 3420 Comm: kworker/u8:15 Not tainted syzkaller #0 PREEMPT_{RT,(full)} Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026 Workqueue: netns cleanup_net RIP: 0010:refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25 Code: eb 66 85 db 74 3e 83 fb 01 75 4c e8 1b f1 22 fd 48 8d 3d 84 cb f1 0a 67 48 0f b9 3a eb 4a e8 08 f1 22 fd 48 8d 3d 81 cb f1 0a <67> 48 0f b9 3a eb 37 e8 f5 f0 22 fd 48 8d 3d 7e cb f1 0a 67 48 0f RSP: 0018:ffffc9000f2c7270 EFLAGS: 00010293 RAX: ffffffff84a18858 RBX: 0000000000000002 RCX: ffff888032ff9ec0 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff8f9353e0 RBP: 0000000000000000 R08: ffff888032ff9ec0 R09: 0000000000000005 R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880570cc000 R13: dffffc0000000000 R14: ffff88802b40563c R15: ffff8880570cc000 FS: 0000000000000000(0000) GS:ffff888126173000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fb1f4d5d000 CR3: 000000006072a000 CR4: 00000000003526f0 Call Trace: <TASK> __refcount_add include/linux/refcount.h:-1 [inline] __refcount_inc include/linux/refcount.h:366 [inline] refcount_inc include/linux/refcount.h:383 [inline] fib_info_hold include/net/ip_fib.h:629 [inline] nsim_fib4_prepare_event drivers/net/netdevsim/fib.c:930 [inline] nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1000 [inline] nsim_fib_event_nb+0x1055/0x1240 drivers/net/netdevsim/fib.c:1043 call_fib_notifier+0x45/0x80 net/core/fib_notifier.c:25 call_fib_entry_notifier net/ipv4/fib_trie.c:90 [inline] fib_leaf_notify net/ipv4/fib_trie.c:2176 [inline] fib_table_notify net/ipv4/fib_trie.c:2194 [inline] fib_notify+0x36b/0x5e0 net/ipv4/fib_trie.c:2217 fib_net_dump net/core/fib_notifier.c:70 [inline] register_fib_notifier+0x184/0x360 net/core/fib_notifier.c:108 nsim_fib_create+0x85d/0x9f0 drivers/net/netdevsim/fib.c:1596 nsim_dev_reload_create drivers/net/netdevsim/dev.c:1604 [inline] nsim_dev_reload_up+0x374/0x7c0 drivers/net/netdevsim/dev.c:1058 devlink_reload+0x501/0x8d0 net/devlink/dev.c:475 devlink_pernet_pre_exit+0x1ff/0x420 net/devlink/core.c:558 ops_pre_exit_list net/core/net_namespace.c:161 [inline] ops_undo_list+0x187/0x940 net/core/net_namespace.c:234 cleanup_net+0x56e/0x800 net/core/net_namespace.c:702 process_one_work kernel/workqueue.c:3314 [inline] process_scheduled_works+0xb5d/0x1860 kernel/workqueue.c:3397 worker_thread+0xa53/0xfc0 kernel/workqueue.c:3478 kthread+0x388/0x470 kernel/kthread.c:436 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK>Fixes 0ae3eb7b4611 ("netdevsim: fib: Perform the route programming in a non-atomic context")Fixes c3852ef7f2f8 ("ipv4: fib: Replay events when registering FIB notifier")Reported-by [email protected]Signed-off-by Kuniyuki Iwashima <[email protected]>
Quoted 5 lines
--- include/net/ip_fib.h | 5 +++++ net/ipv4/fib_trie.c | 4 ++++ 2 files changed, 9 insertions(+)
PATCH 2/2 net: fib_rules: Don't dump dying fib_rule in fib_rules_dump().
In reply to Kuniyuki Iwashimarocker_router_fib_event() calls fib_rule_get() during RCU dump.
If the fib_rule is dying, refcount_inc() will complain about it.
Let's call refcount_inc_not_zero() in fib_rules_dump().
--- include/net/fib_rules.h | 5 +++++ net/core/fib_rules.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-)
include/net/fib_rules.h +5 -0
@@ -111,6 +111,11 @@ static inline void fib_rule_get(struct fib_rule *rule)refcount_inc (&rule->refcnt); } +static inline bool fib_rule_get_safe (struct fib_rule *rule) +{ +return refcount_inc_not_zero (&rule->refcnt); +} +static inline void fib_rule_put (struct fib_rule *rule) {if (refcount_dec_and_test (&rule->refcnt))
net/core/fib_rules.c +5 -1
@@ -349,7 +349,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,if (err != -EAGAIN ) {if ((arg->flags &FIB_LOOKUP_NOREF ) || -likely (refcount_inc_not_zero (&rule->refcnt))) { +likely (fib_rule_get_safe (rule))) { arg->rule = rule; goto out; }
@@ -410,8 +410,12 @@ int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,if (!ops)return -EAFNOSUPPORT ;list_for_each_entry_rcu (rule, &ops->rules_list, list) { +if (!fib_rule_get_safe (rule)) +continue ; + err =call_fib_rule_notifier (nb,FIB_EVENT_RULE_ADD , rule, family, extack); +fib_rule_put (rule);if (err)break ; }
Signature · 1 line
2.54.0.1099.g489fc7bff1-goog
Re: [PATCH v1 net 2/2] net: fib_rules: Don't dump dying fib_rule in fib_rules_dump().
Quoted 8 lines · Kuniyuki Iwashima
rocker_router_fib_event()callsfib_rule_get()during RCU dump.If the
fib_ruleis dying,refcount_inc()will complain about it.Let's call
refcount_inc_not_zero()infib_rules_dump().Fixes 5d7bfd141924 ("ipv4: fib_rules: Dump FIB rules when registering FIB notifier")Signed-off-by Kuniyuki Iwashima <[email protected]>
Re: [PATCH v1 net 2/2] net: fib_rules: Don't dump dying fib_rule in fib_rules_dump().
In reply to Kuniyuki IwashimaQuoted 4 lines · Kuniyuki Iwashima
rocker_router_fib_event()callsfib_rule_get()during RCU dump.If the
fib_ruleis dying,refcount_inc()will complain about it.
Quoted 9 lines
Let's call
refcount_inc_not_zero()infib_rules_dump().Fixes 5d7bfd141924 ("ipv4: fib_rules: Dump FIB rules when registering FIB notifier")Signed-off-by Kuniyuki Iwashima <[email protected]>--- include/net/fib_rules.h | 5 +++++ net/core/fib_rules.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-)
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 8 lines · On Wed, 10 Jun 2026 06:17:17 +0000 you wrote:
syzbot reported
fib_infoUAF in netdevsim, and the same bug exists in rocker and mlxsw.Patch 1 fixes it, and Patch 2 fixes the same type of bug of
fib_rule.[...]
Here is the summary with links:
- [v1,net,1/2] ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
https://git.kernel.org/netdev/net/c/06b693d2eb66 - [v1,net,2/2] net: fib_rules: Don't dump dying fib_rule in fib_rules_dump(). https://git.kernel.org/netdev/net/c/2821e85c058f
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html