diff mbox series

[19/26] netfilter: nf_queue: do not release refcouts until nf_reinject is done

Message ID 20200330003708.54017-20-pablo@netfilter.org
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series [01/26] netfilter: nf_tables: move nft_expr_clone() to nf_tables_api.c | expand

Commit Message

Pablo Neira Ayuso March 30, 2020, 12:37 a.m. UTC
From: Florian Westphal <fw@strlen.de>

nf_queue is problematic when another NF_QUEUE invocation happens
from nf_reinject().

1. nf_queue is invoked, increments state->sk refcount.
2. skb is queued, waiting for verdict.
3. sk is closed/released.
3. verdict comes back, nf_reinject is called.
4. nf_reinject drops the reference -- refcount can now drop to 0

Instead of get_ref/release_ref pattern, we need to nest the get_ref calls:

So that when we invoke the next processing stage (another netfilter
or the okfn()), we hold at least one reference count on the

After previous patch, it is now safe to put the entry even after okfn()
has potentially free'd the skb.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
 net/netfilter/nf_queue.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
diff mbox series


diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 96eb72908467..aadccdd117f0 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -303,12 +303,10 @@  void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 	hooks = nf_hook_entries_head(net, pf, entry->state.hook);
-	nf_queue_entry_release_refs(entry);
 	i = entry->hook_index;
 	if (WARN_ON_ONCE(!hooks || i >= hooks->num_hook_entries)) {
-		kfree(entry);
+		nf_queue_entry_free(entry);
@@ -347,6 +345,6 @@  void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
-	kfree(entry);
+	nf_queue_entry_free(entry);