diff options
| author | Kuniyuki Iwashima <kuniyu@google.com> | 2026-06-12 09:32:04 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-06-15 21:49:28 +0300 |
| commit | 64587e936b6526539f5d2cf1bb667c52be937cd7 (patch) | |
| tree | c527801fc4e7b5bc7686e0004226cf187d061c5a | |
| parent | e3d202a1ed7c37c3c936d5eeb3abc3a7a713cb95 (diff) | |
| download | linux-64587e936b6526539f5d2cf1bb667c52be937cd7.tar.xz | |
ipv4: fib: Flush all fib_info in fib_table_flush() during netns dismantle.
Even when fib_table_flush() is called with flush_all true, it does
not flush all fib_info due to this condition:
!(fi->fib_flags & RTNH_F_DEAD) && !fib_props[fa->fa_type].error)
This creates an implicit ordering between default_device_exit_batch()
and fib_net_exit_batch().
fib_table_flush(flush_all=true) must be called after all devices
are NETDEV_UNREGISTERed, which is after nexthop_flush_dev() marks
RTNH_F_DEAD.
This would cause memory leak if the order were reversed.
fib_table_flush() does not skip non-dead error routes when flush_all
is true:
!flush_all &&
!(fi->fib_flags & RTNH_F_DEAD) && fib_props[fa->fa_type].error
Let's merge the two conditions not to skip all non-dead fib_info
during netns dismantle.
Note that we could further apply !flush_all to the basic table
id check and the rtmsg_fib() call in the loop.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260612063225.455191-2-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | net/ipv4/fib_trie.c | 10 |
1 files changed, 2 insertions, 8 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 1308213791f1..07068207b888 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2046,18 +2046,12 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) { struct fib_info *fi = fa->fa_info; - if (!fi || tb->tb_id != fa->tb_id || - (!(fi->fib_flags & RTNH_F_DEAD) && - !fib_props[fa->fa_type].error)) { + if (!fi || tb->tb_id != fa->tb_id) { slen = fa->fa_slen; continue; } - /* When not flushing the entire table, skip error - * routes that are not marked for deletion. - */ - if (!flush_all && fib_props[fa->fa_type].error && - !(fi->fib_flags & RTNH_F_DEAD)) { + if (!flush_all && !(fi->fib_flags & RTNH_F_DEAD)) { slen = fa->fa_slen; continue; } |
