From: Kuniyuki Iwashima Date: Fri, 12 Jun 2026 06:32:04 +0000 (+0000) Subject: ipv4: fib: Flush all fib_info in fib_table_flush() during netns dismantle. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64587e936b6526539f5d2cf1bb667c52be937cd7;p=thirdparty%2Fkernel%2Flinux.git 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 Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20260612063225.455191-2-kuniyu@google.com Signed-off-by: Jakub Kicinski --- diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 1308213791f19..07068207b8885 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; }