Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_queue: handle socket prefetch

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>

+12
+12
net/netfilter/nf_queue.c
··· 180 180 break; 181 181 } 182 182 183 + if (skb_sk_is_prefetched(skb)) { 184 + struct sock *sk = skb->sk; 185 + 186 + if (!sk_is_refcounted(sk)) { 187 + if (!refcount_inc_not_zero(&sk->sk_refcnt)) 188 + return -ENOTCONN; 189 + 190 + /* drop refcount on skb_orphan */ 191 + skb->destructor = sock_edemux; 192 + } 193 + } 194 + 183 195 entry = kmalloc(sizeof(*entry) + route_key_size, GFP_ATOMIC); 184 196 if (!entry) 185 197 return -ENOMEM;