diff options
author | Florian Westphal <fw@strlen.de> | 2022-03-01 02:46:19 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-03-08 21:09:33 +0300 |
commit | 81f817f3e559d3e4e56110f6132f8322a97fbc8c (patch) | |
tree | dbab396a06ad7b100514df77be9d7442294580fa /net/netfilter | |
parent | 4d05239203fa38ea8a6f31e228460da4cb17a71a (diff) | |
download | linux-81f817f3e559d3e4e56110f6132f8322a97fbc8c.tar.xz |
netfilter: nf_queue: handle socket prefetch
commit 3b836da4081fa585cf6c392f62557496f2cb0efe upstream.
In case someone combines bpf socket assign and nf_queue, then we will
queue an skb who references a struct sock that did not have its
reference count incremented.
As we leave rcu protection, there is no guarantee that skb->sk is still
valid.
For refcount-less skb->sk case, try to increment the reference count
and then override the destructor.
In case of failure we have two choices: orphan the skb and 'delete'
preselect or let nf_queue() drop the packet.
Do the latter, it should not happen during normal operation.
Fixes: cf7fbe660f2d ("bpf: Add socket assign support")
Acked-by: Joe Stringer <joe@cilium.io>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_queue.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 543904249f7e..bb8607ff94bc 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -189,6 +189,18 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, break; } + if (skb_sk_is_prefetched(skb)) { + struct sock *sk = skb->sk; + + if (!sk_is_refcounted(sk)) { + if (!refcount_inc_not_zero(&sk->sk_refcnt)) + return -ENOTCONN; + + /* drop refcount on skb_orphan */ + skb->destructor = sock_edemux; + } + } + entry = kmalloc(sizeof(*entry) + route_key_size, GFP_ATOMIC); if (!entry) return -ENOMEM; |