netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 nf 0/2] netfilter: nf_queue: be more careful with sk refcounts
@ 2022-03-01  0:21 Florian Westphal
  2022-03-01  0:21 ` [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free Florian Westphal
  2022-03-01  0:21 ` [PATCH v2 nf 2/2] netfilter: nf_queue: handle socket prefetch Florian Westphal
  0 siblings, 2 replies; 4+ messages in thread
From: Florian Westphal @ 2022-03-01  0:21 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This is a resend of v1 patch, split into two distinct patches
to ease backport work.

Florian Westphal (2):
  netfilter: nf_queue: fix possible use-after-free
  netfilter: nf_queue: handle socket prefetch

 include/net/netfilter/nf_queue.h |  2 +-
 net/netfilter/nf_queue.c         | 25 +++++++++++++++++++++----
 net/netfilter/nfnetlink_queue.c  | 12 +++++++++---
 3 files changed, 31 insertions(+), 8 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free
  2022-03-01  0:21 [PATCH v2 nf 0/2] netfilter: nf_queue: be more careful with sk refcounts Florian Westphal
@ 2022-03-01  0:21 ` Florian Westphal
  2022-03-01  1:34   ` Eric Dumazet
  2022-03-01  0:21 ` [PATCH v2 nf 2/2] netfilter: nf_queue: handle socket prefetch Florian Westphal
  1 sibling, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2022-03-01  0:21 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal, Eric Dumazet

Eric Dumazet says:
  The sock_hold() side seems suspect, because there is no guarantee
  that sk_refcnt is not already 0.

On failure, we cannot queue the packet and need to indicate an
error.  The packet will be dropped by the caller.

v2: split skb prefetch hunk into separate change

Fixes: 271b72c7fa82c ("udp: RCU handling for Unicast packets.")
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/netfilter/nf_queue.h |  2 +-
 net/netfilter/nf_queue.c         | 13 +++++++++----
 net/netfilter/nfnetlink_queue.c  | 12 +++++++++---
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 9eed51e920e8..980daa6e1e3a 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -37,7 +37,7 @@ void nf_register_queue_handler(const struct nf_queue_handler *qh);
 void nf_unregister_queue_handler(void);
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 
-void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
+bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
 void nf_queue_entry_free(struct nf_queue_entry *entry);
 
 static inline void init_hashrandom(u32 *jhash_initval)
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 5ab0680db445..e39549c55945 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -96,19 +96,21 @@ static void __nf_queue_entry_init_physdevs(struct nf_queue_entry *entry)
 }
 
 /* Bump dev refs so they don't vanish while packet is out */
-void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
+bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
 {
 	struct nf_hook_state *state = &entry->state;
 
+	if (state->sk && !refcount_inc_not_zero(&state->sk->sk_refcnt))
+		return false;
+
 	dev_hold(state->in);
 	dev_hold(state->out);
-	if (state->sk)
-		sock_hold(state->sk);
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 	dev_hold(entry->physin);
 	dev_hold(entry->physout);
 #endif
+	return true;
 }
 EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
 
@@ -196,7 +198,10 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
 
 	__nf_queue_entry_init_physdevs(entry);
 
-	nf_queue_entry_get_refs(entry);
+	if (!nf_queue_entry_get_refs(entry)) {
+		kfree(entry);
+		return -ENOTCONN;
+	}
 
 	switch (entry->state.pf) {
 	case AF_INET:
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index ea2d9c2a44cf..64a6acb6aeae 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -710,9 +710,15 @@ static struct nf_queue_entry *
 nf_queue_entry_dup(struct nf_queue_entry *e)
 {
 	struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
-	if (entry)
-		nf_queue_entry_get_refs(entry);
-	return entry;
+
+	if (!entry)
+		return NULL;
+
+	if (nf_queue_entry_get_refs(entry))
+		return entry;
+
+	kfree(entry);
+	return NULL;
 }
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 nf 2/2] netfilter: nf_queue: handle socket prefetch
  2022-03-01  0:21 [PATCH v2 nf 0/2] netfilter: nf_queue: be more careful with sk refcounts Florian Westphal
  2022-03-01  0:21 ` [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free Florian Westphal
@ 2022-03-01  0:21 ` Florian Westphal
  1 sibling, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2022-03-01  0:21 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal, Joe Stringer

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>
---
 net/netfilter/nf_queue.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index e39549c55945..63d1516816b1 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -180,6 +180,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;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free
  2022-03-01  0:21 ` [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free Florian Westphal
@ 2022-03-01  1:34   ` Eric Dumazet
  0 siblings, 0 replies; 4+ messages in thread
From: Eric Dumazet @ 2022-03-01  1:34 UTC (permalink / raw)
  To: Florian Westphal, netfilter-devel


On 2/28/22 16:21, Florian Westphal wrote:
> Eric Dumazet says:
>    The sock_hold() side seems suspect, because there is no guarantee
>    that sk_refcnt is not already 0.
>
> On failure, we cannot queue the packet and need to indicate an
> error.  The packet will be dropped by the caller.
>
> v2: split skb prefetch hunk into separate change
>
> Fixes: 271b72c7fa82c ("udp: RCU handling for Unicast packets.")
> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---


SGTM, thanks !

Reviewed-by: Eric Dumazet <edumazet@google.com>



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-03-01  1:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-01  0:21 [PATCH v2 nf 0/2] netfilter: nf_queue: be more careful with sk refcounts Florian Westphal
2022-03-01  0:21 ` [PATCH v2 nf 1/2] netfilter: nf_queue: fix possible use-after-free Florian Westphal
2022-03-01  1:34   ` Eric Dumazet
2022-03-01  0:21 ` [PATCH v2 nf 2/2] netfilter: nf_queue: handle socket prefetch Florian Westphal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).