BPF List
 help / color / mirror / Atom feed
* [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks
@ 2026-07-07  4:23 Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 1/4] selftests/bpf: Ensure UDP sockets are bound Michal Luczaj
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Michal Luczaj @ 2026-07-07  4:23 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Eric Dumazet,
	Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
	Jakub Kicinski, Simon Horman, Cong Wang
  Cc: Michal Luczaj, bpf, linux-kselftest, linux-kernel, netdev

Fix for UDP sockets getting leaked during sockmap lookup/release.
Accompanied by selftests updates.

Two Sashiko's concerns to be addressed separately:
https://lore.kernel.org/bpf/20260626205814.BAC3C1F000E9@smtp.kernel.org/

Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
Changes in v4:
- selftest: drop redundant `if (err)` [Sashiko]
- Link to v3: https://patch.msgid.link/20260702-sockmap-lookup-udp-leak-v3-0-ff8de8782468@rbox.co

Changes in v3:
- selftest: better error handling, ASSERT_*() macros [Sashiko]
- selftest: fix grammar, reorder patches [Kuniyuki]
- Link to v2: https://patch.msgid.link/20260626-sockmap-lookup-udp-leak-v2-0-7e7e201c951a@rbox.co

Changes in v2:
- selftest: drop the original, adapt old tests
- fix: change approach to rejecting unbound UDP [Kuniyuki]
- Link to v1: https://patch.msgid.link/20260623-sockmap-lookup-udp-leak-v1-0-05804f9308e4@rbox.co

To: Alexei Starovoitov <ast@kernel.org>
To: Daniel Borkmann <daniel@iogearbox.net>
To: Andrii Nakryiko <andrii@kernel.org>
To: Eduard Zingerman <eddyz87@gmail.com>
To: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: Martin KaFai Lau <martin.lau@linux.dev>
To: Song Liu <song@kernel.org>
To: Yonghong Song <yonghong.song@linux.dev>
To: Jiri Olsa <jolsa@kernel.org>
To: Emil Tsalapatis <emil@etsalapatis.com>
To: Shuah Khan <shuah@kernel.org>
To: John Fastabend <john.fastabend@gmail.com>
To: Jakub Sitnicki <jakub@cloudflare.com>
To: Jiayuan Chen <jiayuan.chen@linux.dev>
To: Eric Dumazet <edumazet@google.com>
To: Kuniyuki Iwashima <kuniyu@google.com>
To: Paolo Abeni <pabeni@redhat.com>
To: Willem de Bruijn <willemb@google.com>
To: "David S. Miller" <davem@davemloft.net>
To: Jakub Kicinski <kuba@kernel.org>
To: Simon Horman <horms@kernel.org>
To: Cong Wang <cong.wang@bytedance.com>
Cc: bpf@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org

---
Michal Luczaj (4):
      selftests/bpf: Ensure UDP sockets are bound
      bpf, sockmap: Reject unhashed UDP sockets on sockmap update
      selftests/bpf: Adapt sockmap update error handling
      selftests/bpf: Fail unbound UDP on sockmap update

 net/core/sock_map.c                                 |  2 ++
 .../selftests/bpf/prog_tests/sockmap_basic.c        |  6 +++---
 .../selftests/bpf/prog_tests/sockmap_listen.c       | 21 +++++++++++----------
 tools/testing/selftests/bpf/test_maps.c             | 13 ++++++-------
 4 files changed, 22 insertions(+), 20 deletions(-)
---
base-commit: 17566290dc802b03a8127729b19c5962d63a7947
change-id: 20260617-sockmap-lookup-udp-leak-bc4e5c5481d7

Best regards,
--  
Michal Luczaj <mhal@rbox.co>


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

* [PATCH bpf v4 1/4] selftests/bpf: Ensure UDP sockets are bound
  2026-07-07  4:23 [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks Michal Luczaj
@ 2026-07-07  4:23 ` Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Michal Luczaj
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Michal Luczaj @ 2026-07-07  4:23 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Eric Dumazet,
	Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
	Jakub Kicinski, Simon Horman, Cong Wang
  Cc: Michal Luczaj, bpf, linux-kselftest, linux-kernel, netdev

Update sockmap_basic tests to bind sockets before they are used. This
accommodates the recent change in sockmap that rejects unbound UDP sockets.

Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
 tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
index cb3229711f93..2d22a9058a8e 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
@@ -853,7 +853,7 @@ static void test_sockmap_many_socket(void)
 		return;
 	}
 
-	udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+	udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
 	if (udp < 0) {
 		close(dgram);
 		close(tcp);
@@ -922,7 +922,7 @@ static void test_sockmap_many_maps(void)
 		return;
 	}
 
-	udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+	udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
 	if (udp < 0) {
 		close(dgram);
 		close(tcp);
@@ -993,7 +993,7 @@ static void test_sockmap_same_sock(void)
 		return;
 	}
 
-	udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+	udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
 	if (udp < 0) {
 		close(dgram);
 		close(tcp);

-- 
2.55.0


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

* [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update
  2026-07-07  4:23 [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 1/4] selftests/bpf: Ensure UDP sockets are bound Michal Luczaj
@ 2026-07-07  4:23 ` Michal Luczaj
  2026-07-07  4:53   ` sashiko-bot
  2026-07-07  4:23 ` [PATCH bpf v4 3/4] selftests/bpf: Adapt sockmap update error handling Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update Michal Luczaj
  3 siblings, 1 reply; 7+ messages in thread
From: Michal Luczaj @ 2026-07-07  4:23 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Eric Dumazet,
	Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
	Jakub Kicinski, Simon Horman, Cong Wang
  Cc: Michal Luczaj, bpf, linux-kselftest, linux-kernel, netdev

UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means
sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false.

Because sockmap accepts unbound UDP sockets, a BPF program can increment a
socket's refcount via lookup. If the socket is subsequently bound, the
transition from unbound to bound causes bpf_sk_release() to skip the
decrement of the refcount, causing a memory leak.

unreferenced object 0xffff88810bc2eb40 (size 1984):
  comm "test_progs", pid 2451, jiffies 4295320596
  hex dump (first 32 bytes):
    7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00  ................
    02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00  ...@............
  backtrace (crc bdee079d):
    kmem_cache_alloc_noprof+0x557/0x660
    sk_prot_alloc+0x69/0x240
    sk_alloc+0x30/0x460
    inet_create+0x2ce/0xf80
    __sock_create+0x25b/0x5c0
    __sys_socket+0x119/0x1d0
    __x64_sys_socket+0x72/0xd0
    do_syscall_64+0xa1/0x5f0
    entry_SYSCALL_64_after_hwframe+0x76/0x7e

Instead of special-casing for refcounted sockets, reject unhashed UDP
sockets during sockmap updates, as there is no benefit to supporting those.
This effectively reverts the commit under Fixes, with two exceptions:

1. sock_map_sk_state_allowed() maintains a fall-through `return true`.
2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash
   handler for BPF sockmap usage"), the proto::unhash BPF handler is not
   reintroduced.

Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject
unhashed sockets in bpf_sk_assign").

Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets")
Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
 net/core/sock_map.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index c60ba6d292f9..9efbd8ca7db8 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk)
 {
 	if (sk_is_tcp(sk))
 		return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN);
+	if (sk_is_udp(sk))
+		return sk_hashed(sk);
 	if (sk_is_stream_unix(sk))
 		return (1 << READ_ONCE(sk->sk_state)) & TCPF_ESTABLISHED;
 	if (sk_is_vsock(sk) &&

-- 
2.55.0


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

* [PATCH bpf v4 3/4] selftests/bpf: Adapt sockmap update error handling
  2026-07-07  4:23 [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 1/4] selftests/bpf: Ensure UDP sockets are bound Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Michal Luczaj
@ 2026-07-07  4:23 ` Michal Luczaj
  2026-07-07  4:23 ` [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update Michal Luczaj
  3 siblings, 0 replies; 7+ messages in thread
From: Michal Luczaj @ 2026-07-07  4:23 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Eric Dumazet,
	Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
	Jakub Kicinski, Simon Horman, Cong Wang
  Cc: Michal Luczaj, bpf, linux-kselftest, linux-kernel, netdev

Update sockmap_listen to accommodate the recent change in sockmap that
rejects unbound UDP sockets.

TCP: Reject unbound and bound (unless established or listening).
UDP: Accept only bound sockets.

While at it, migrate to ASSERT_* and enforce reverse xmas tree.

Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
 .../selftests/bpf/prog_tests/sockmap_listen.c       | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
index cc0c68bab907..1c96a3cf4b97 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
@@ -53,8 +53,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
 			       int family, int sotype, int mapfd)
 {
 	u32 key = 0;
-	u64 value;
 	int err, s;
+	u64 value;
 
 	s = xsocket(family, sotype, 0);
 	if (s == -1)
@@ -63,11 +63,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
 	errno = 0;
 	value = s;
 	err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
-	if (sotype == SOCK_STREAM) {
-		if (!err || errno != EOPNOTSUPP)
-			FAIL_ERRNO("map_update: expected EOPNOTSUPP");
-	} else if (err)
-		FAIL_ERRNO("map_update: expected success");
+	ASSERT_ERR(err, "map_update");
+	ASSERT_EQ(errno, EOPNOTSUPP, "errno");
 	xclose(s);
 }
 
@@ -77,8 +74,8 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
 	struct sockaddr_storage addr;
 	socklen_t len = 0;
 	u32 key = 0;
-	u64 value;
 	int err, s;
+	u64 value;
 
 	init_addr_loopback(family, &addr, &len);
 
@@ -93,8 +90,12 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
 	errno = 0;
 	value = s;
 	err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
-	if (!err || errno != EOPNOTSUPP)
-		FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+	if (sotype == SOCK_STREAM) {
+		ASSERT_ERR(err, "map_update");
+		ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+	} else {
+		ASSERT_OK(err, "map_update");
+	}
 close:
 	xclose(s);
 }
@@ -1289,7 +1290,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
 		/* insert */
 		TEST(test_insert_invalid),
 		TEST(test_insert_opened),
-		TEST(test_insert_bound, SOCK_STREAM),
+		TEST(test_insert_bound),
 		TEST(test_insert),
 		/* delete */
 		TEST(test_delete_after_insert),

-- 
2.55.0


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

* [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update
  2026-07-07  4:23 [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks Michal Luczaj
                   ` (2 preceding siblings ...)
  2026-07-07  4:23 ` [PATCH bpf v4 3/4] selftests/bpf: Adapt sockmap update error handling Michal Luczaj
@ 2026-07-07  4:23 ` Michal Luczaj
  2026-07-07  4:31   ` sashiko-bot
  3 siblings, 1 reply; 7+ messages in thread
From: Michal Luczaj @ 2026-07-07  4:23 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Eric Dumazet,
	Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
	Jakub Kicinski, Simon Horman, Cong Wang
  Cc: Michal Luczaj, bpf, linux-kselftest, linux-kernel, netdev

sockmap now rejects unbound UDP sockets. Adjust test_maps. While at it,
check socket()'s return value.

This effectively reverts commit c39aa2159974 ("bpf, selftests: Fix
test_maps now that sockmap supports UDP").

Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
 tools/testing/selftests/bpf/test_maps.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index c32da7bd8be2..6a2641ee7897 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -759,16 +759,15 @@ static void test_sockmap(unsigned int tasks, void *data)
 		goto out_sockmap;
 	}
 
-	/* Test update with unsupported UDP socket */
+	/* Test update with unsupported unbound UDP socket */
 	udp = socket(AF_INET, SOCK_DGRAM, 0);
-	i = 0;
-	err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
-	if (err) {
-		printf("Failed socket update SOCK_DGRAM '%i:%i'\n",
-		       i, udp);
+	CHECK(udp < 0, "socket(AF_INET, SOCK_DGRAM)", "errno:%d\n", errno);
+	err = bpf_map_update_elem(fd, &(int){0}, &udp, BPF_ANY);
+	close(udp);
+	if (!err) {
+		printf("Unexpectedly succeeded unbound UDP update '0:%i'\n", udp);
 		goto out_sockmap;
 	}
-	close(udp);
 
 	/* Test update without programs */
 	for (i = 0; i < 6; i++) {

-- 
2.55.0


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

* Re: [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update
  2026-07-07  4:23 ` [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update Michal Luczaj
@ 2026-07-07  4:31   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-07  4:31 UTC (permalink / raw)
  To: Michal Luczaj; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Usage of the deprecated CHECK() macro in new patch code.
--

--- Patch [4]: [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update ---
commit 97dab8be7b651b7cede0184ca7321b97bf080f13
Author: Michal Luczaj <mhal@rbox.co>

selftests/bpf: Fail unbound UDP on sockmap update

This commit adjusts test_maps to reflect that sockmap now rejects unbound
UDP sockets. It adds a check for the socket() return value and effectively
reverts an earlier commit.

> diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
> --- a/tools/testing/selftests/bpf/test_maps.c
> +++ b/tools/testing/selftests/bpf/test_maps.c
> @@ -759,16 +759,15 @@ static void test_sockmap(unsigned int tasks, void *data)
>  		goto out_sockmap;
>  	}
>  
> -	/* Test update with unsupported UDP socket */
> +	/* Test update with unsupported unbound UDP socket */
>  	udp = socket(AF_INET, SOCK_DGRAM, 0);
> -	i = 0;
> -	err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
> -	if (err) {
> -		printf("Failed socket update SOCK_DGRAM '%i:%i'\n",
> -		       i, udp);
> +	CHECK(udp < 0, "socket(AF_INET, SOCK_DGRAM)", "errno:%d\n", errno);

[Severity: Low]
This isn't a bug, but could we use ASSERT_OK_FD() or ASSERT_GE() instead of
the deprecated CHECK() macro here? 

The BPF subsystem coding guidelines prefer using the modern ASSERT_* family
of macros for new tests and updates.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260707-sockmap-lookup-udp-leak-v4-0-f878346f27ab@rbox.co?part=4

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

* Re: [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update
  2026-07-07  4:23 ` [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Michal Luczaj
@ 2026-07-07  4:53   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-07  4:53 UTC (permalink / raw)
  To: Michal Luczaj; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] The patch prevents a refcount leak for UDP sockets by rejecting unhashed sockets, but an identical reference count leak can be triggered for TCP sockets because `sk_is_refcounted()` relies on the mutable `SOCK_RCU_FREE` flag.
--

--- Patch [2]: [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update ---
commit efe688dfced966a49066087e860ab73696a8f75a
Author: Michal Luczaj <mhal@rbox.co>
Date:   Tue Jul 7 04:23:57 2026 +0000

bpf, sockmap: Reject unhashed UDP sockets on sockmap update

This patch addresses a socket reference count leak by preventing unhashed UDP
sockets from being updated in sockmaps. It removes the ability for BPF programs
to increment a refcount on an unbound socket that subsequently gets bound and
skips the refcount decrement upon release.

> diff --git a/net/core/sock_map.c b/net/core/sock_map.c
> --- a/net/core/sock_map.c
> +++ b/net/core/sock_map.c
> @@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk)
>  {
>  	if (sk_is_tcp(sk))
>  		return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN);

[Severity: High]
This is a pre-existing issue, but can the exact same reference count leak
happen for TCP sockets because sk_is_refcounted() relies on the mutable
SOCK_RCU_FREE flag?

If a user creates a TCP socket, connects it (entering TCP_ESTABLISHED), and
adds it to a sockmap, a BPF program can call bpf_map_lookup_elem() on the
sockmap. This increments the socket's refcount because SOCK_RCU_FREE is not
set on established sockets.

If a user thread concurrently calls connect(AF_UNSPEC) to disconnect the
socket (moving it to TCP_CLOSE and removing it from the map), and then calls
listen() on the same socket, inet_hash() unconditionally sets the
SOCK_RCU_FREE flag.

When the BPF program subsequently calls bpf_sk_release(sk):

net/core/filter.c:bpf_sk_release() {
    ...
    if (sk && sk_is_refcounted(sk))
        sock_gen_put(sk);
    ...
}

sk_is_refcounted(sk) will now return false because SOCK_RCU_FREE is set,
causing bpf_sk_release() to skip the decrement and permanently leak the
acquired reference. 

Could this sequence be abused to cause memory exhaustion, and is there a way
to safely track the acquired references without relying on a flag that might
change mid-flight?

> +	if (sk_is_udp(sk))
> +		return sk_hashed(sk);
>  	if (sk_is_stream_unix(sk))
>  		return (1 << READ_ONCE(sk->sk_state)) & TCPF_ESTABLISHED;
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260707-sockmap-lookup-udp-leak-v4-0-f878346f27ab@rbox.co?part=2

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

end of thread, other threads:[~2026-07-07  4:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07  4:23 [PATCH bpf v4 0/4] bpf, sockmap: Fix sockmap leaking UDP socks Michal Luczaj
2026-07-07  4:23 ` [PATCH bpf v4 1/4] selftests/bpf: Ensure UDP sockets are bound Michal Luczaj
2026-07-07  4:23 ` [PATCH bpf v4 2/4] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Michal Luczaj
2026-07-07  4:53   ` sashiko-bot
2026-07-07  4:23 ` [PATCH bpf v4 3/4] selftests/bpf: Adapt sockmap update error handling Michal Luczaj
2026-07-07  4:23 ` [PATCH bpf v4 4/4] selftests/bpf: Fail unbound UDP on sockmap update Michal Luczaj
2026-07-07  4:31   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox