| Message ID | 20260929130939.17872-1-fw@strlen.de |
|---|---|
| State | New |
| Headers | show |
| Series | [nf-next] netfilter: conntrack: fix unlikely UaF in gc worker | expand |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index d0d9e5ea84a0..6cba999e8056 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -2507,6 +2507,11 @@ void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list) goto i_see_dead_people; } + /* must wait for current scan loop, worker also looks at + * struct nf_conntrack_net, which is about to be free'd. + */ + flush_work(&conntrack_gc_work.dwork.work); + list_for_each_entry(net, net_exit_list, exit_list) { warn_on_keymap_list_leak(net); nf_conntrack_ecache_pernet_fini(net);
When early-drop scan is enabled, gc_worker() reads tmp->ct_net, resolves cnet with nf_ct_pernet(), and reads cnet->count with RCU read lock held but before acquiring a reference to tmp. Its unlikely but possible that the worker gets preempted before reading cnet->count while nf_conntrack_cleanup_net_list manages to unlink all conntracks and returns in the mean time. This allows for the pernet memory to get free'd. On resume, use after free would occur when the worker reads cnet->count. This can be solved either via another synchronize_rcu() in nf_conntrack_cleanup_net_list or via cheaper flush_work(). If work wasn't running no race can happen as next call cannot observe already-unlinked conntrack objects. This is an LLM finding with no reproducer, but it appears to be correct. Fixes: c6dd940b1f74 ("netfilter: allow early drop of assured conntracks") Reported-by: Vega <vega@nebusec.ai> Signed-off-by: Florian Westphal <fw@strlen.de> --- net/netfilter/nf_conntrack_core.c | 5 +++++ 1 file changed, 5 insertions(+)