A packet queued to userspace keeps its conntrack reference in skb->_nfct until the verdict arrives. The conntrack hooks sit at prerouting, local in, local out and postrouting; a packet queued from the forward hook point is covered by none of them. Until commit 72ac1c0937df ("netfilter: nf_queue: limit the hook drop flush to the unregistered hook point") unregistering the conntrack hooks flushed every queued packet of the network namespace and released those references. The flush now only covers the hook points of the removed hooks. Packets queued from forward keep their nf_conn alive, and nf_conntrack_cleanup_net_list() loops on cnet->count, with pernet_ops_rwsem held for write, until userspace sends a verdict or closes the queue. Flush every queued packet of the namespaces being cleaned up in nf_conntrack_cleanup_net_list(), after the synchronize_rcu_expedited() that waits for the packets still inside the hooks, so that a packet a hook was processing while the hooks were removed is dropped as well. Reproduced in virtme-ng with nf_conntrack built as a module and loaded with enable_hooks=1: two network namespaces routed through the host namespace, an ip forward chain that sends udp dport 12345 to queue 1, and the nf_queue selftest helper holding the verdicts (-H). With 10 packets queued and 10 conntrack entries, rmmod nf_conntrack blocks until the verdicts are sent, 15 s later in the test. With this patch rmmod returns at once, the 10 entries are dropped and the verdict fails with -ENOENT. nft_queue.sh passes. The code and this commit message were written with an LLM coding assistant from the review linked below. The author reviewed the result and validated it with the reproducer and the selftest. Fixes: 72ac1c0937df ("netfilter: nf_queue: limit the hook drop flush to the unregistered hook point") Reported-by: Sashiko (nipa) Closes: https://lore.kernel.org/netfilter-devel/179237288267.3135.9555179349652175002@kernel.org/ Suggested-by: Florian Westphal Assisted-by: LLM Signed-off-by: Antonio Ojea --- net/netfilter/nf_conntrack_core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 42a7cbdbd7d5..3ccee38beb1f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -2490,6 +2490,12 @@ void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list) * delete... */ synchronize_rcu_expedited(); + + /* Packets queued to userspace hold nf_conn references; the hook + * removal only flushed the hook points conntrack was registered at. + */ + list_for_each_entry(net, net_exit_list, exit_list) + nf_queue_nf_hook_drop(net, NULL); i_see_dead_people: busy = 0; list_for_each_entry(net, net_exit_list, exit_list) { -- 2.56.0.218.g1ec904b173-goog