* [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak
@ 2025-01-10 13:21 Michal Luczaj
2025-01-11 0:44 ` Martin KaFai Lau
2025-01-11 2:10 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Michal Luczaj @ 2025-01-10 13:21 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Mykola Lysenko, Shuah Khan, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Jakub Sitnicki
Cc: bpf, netdev, Michal Luczaj
As pointed out in the original comment, lookup in sockmap can return a TCP
ESTABLISHED socket. Such TCP socket may have had SO_ATTACH_REUSEPORT_EBPF
set before it was ESTABLISHED. In other words, a non-NULL sk_reuseport_cb
does not imply a non-refcounted socket.
Drop sk's reference in both error paths.
unreferenced object 0xffff888101911800 (size 2048):
comm "test_progs", pid 44109, jiffies 4297131437
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace (crc 9336483b):
__kmalloc_noprof+0x3bf/0x560
__reuseport_alloc+0x1d/0x40
reuseport_alloc+0xca/0x150
reuseport_attach_prog+0x87/0x140
sk_reuseport_attach_bpf+0xc8/0x100
sk_setsockopt+0x1181/0x1990
do_sock_setsockopt+0x12b/0x160
__sys_setsockopt+0x7b/0xc0
__x64_sys_setsockopt+0x1b/0x30
do_syscall_64+0x93/0x180
entry_SYSCALL_64_after_hwframe+0x76/0x7e
Fixes: 64d85290d79c ("bpf: Allow bpf_map_lookup_elem for SOCKMAP and SOCKHASH")
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
net/core/filter.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index 834614071727ab92cee759dc788ec2ee6f92284b..2fb45a86f3ddbffa9fd55885d4c4c0d8c3a6c381 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -11251,6 +11251,7 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
bool is_sockarray = map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY;
struct sock_reuseport *reuse;
struct sock *selected_sk;
+ int err;
selected_sk = map->ops->map_lookup_elem(map, key);
if (!selected_sk)
@@ -11258,10 +11259,6 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
reuse = rcu_dereference(selected_sk->sk_reuseport_cb);
if (!reuse) {
- /* Lookup in sock_map can return TCP ESTABLISHED sockets. */
- if (sk_is_refcounted(selected_sk))
- sock_put(selected_sk);
-
/* reuseport_array has only sk with non NULL sk_reuseport_cb.
* The only (!reuse) case here is - the sk has already been
* unhashed (e.g. by close()), so treat it as -ENOENT.
@@ -11269,24 +11266,33 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
* Other maps (e.g. sock_map) do not provide this guarantee and
* the sk may never be in the reuseport group to begin with.
*/
- return is_sockarray ? -ENOENT : -EINVAL;
+ err = is_sockarray ? -ENOENT : -EINVAL;
+ goto error;
}
if (unlikely(reuse->reuseport_id != reuse_kern->reuseport_id)) {
struct sock *sk = reuse_kern->sk;
- if (sk->sk_protocol != selected_sk->sk_protocol)
- return -EPROTOTYPE;
- else if (sk->sk_family != selected_sk->sk_family)
- return -EAFNOSUPPORT;
-
- /* Catch all. Likely bound to a different sockaddr. */
- return -EBADFD;
+ if (sk->sk_protocol != selected_sk->sk_protocol) {
+ err = -EPROTOTYPE;
+ } else if (sk->sk_family != selected_sk->sk_family) {
+ err = -EAFNOSUPPORT;
+ } else {
+ /* Catch all. Likely bound to a different sockaddr. */
+ err = -EBADFD;
+ }
+ goto error;
}
reuse_kern->selected_sk = selected_sk;
return 0;
+error:
+ /* Lookup in sock_map can return TCP ESTABLISHED sockets. */
+ if (sk_is_refcounted(selected_sk))
+ sock_put(selected_sk);
+
+ return err;
}
static const struct bpf_func_proto sk_select_reuseport_proto = {
---
base-commit: 1f6ff8756091d99b7e5fa556abc0465328302b8b
change-id: 20250110-reuseport-memleak-9ac6587bd99a
Best regards,
--
Michal Luczaj <mhal@rbox.co>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak
2025-01-10 13:21 [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak Michal Luczaj
@ 2025-01-11 0:44 ` Martin KaFai Lau
2025-01-11 2:10 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Martin KaFai Lau @ 2025-01-11 0:44 UTC (permalink / raw)
To: Michal Luczaj, Jakub Kicinski
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Mykola Lysenko,
Shuah Khan, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Jakub Sitnicki, bpf, netdev
On 1/10/25 5:21 AM, Michal Luczaj wrote:
> As pointed out in the original comment, lookup in sockmap can return a TCP
> ESTABLISHED socket. Such TCP socket may have had SO_ATTACH_REUSEPORT_EBPF
> set before it was ESTABLISHED. In other words, a non-NULL sk_reuseport_cb
> does not imply a non-refcounted socket.
>
> Drop sk's reference in both error paths.
Reviewed-by: Martin KaFai Lau <martin.lau@kernel.org>
Jakub, can you directly take this to the net tree? Thanks!
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak
2025-01-10 13:21 [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak Michal Luczaj
2025-01-11 0:44 ` Martin KaFai Lau
@ 2025-01-11 2:10 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-01-11 2:10 UTC (permalink / raw)
To: Michal Luczaj
Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, mykolal, shuah,
davem, edumazet, kuba, pabeni, horms, jakub, bpf, netdev
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 10 Jan 2025 14:21:55 +0100 you wrote:
> As pointed out in the original comment, lookup in sockmap can return a TCP
> ESTABLISHED socket. Such TCP socket may have had SO_ATTACH_REUSEPORT_EBPF
> set before it was ESTABLISHED. In other words, a non-NULL sk_reuseport_cb
> does not imply a non-refcounted socket.
>
> Drop sk's reference in both error paths.
>
> [...]
Here is the summary with links:
- [bpf] bpf: Fix bpf_sk_select_reuseport() memory leak
https://git.kernel.org/netdev/net/c/b3af60928ab9
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-01-11 2:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-10 13:21 [PATCH bpf] bpf: Fix bpf_sk_select_reuseport() memory leak Michal Luczaj
2025-01-11 0:44 ` Martin KaFai Lau
2025-01-11 2:10 ` patchwork-bot+netdevbpf
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).