Patch "bpf: Fix bpf_sk_select_reuseport() memory leak" has been added to the 6.12-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    bpf: Fix bpf_sk_select_reuseport() memory leak

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     bpf-fix-bpf_sk_select_reuseport-memory-leak.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit bf86ba00e5c71f0b2bbce7c3a95b15b71c46334f
Author: Michal Luczaj <mhal@xxxxxxx>
Date:   Fri Jan 10 14:21:55 2025 +0100

    bpf: Fix bpf_sk_select_reuseport() memory leak
    
    [ Upstream commit b3af60928ab9129befa65e6df0310d27300942bf ]
    
    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@xxxxxxx>
    Reviewed-by: Martin KaFai Lau <martin.lau@xxxxxxxxxx>
    Link: https://patch.msgid.link/20250110-reuseport-memleak-v1-1-fa1ddab0adfe@xxxxxxx
    Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/core/filter.c b/net/core/filter.c
index 54a53fae9e98f..46da488ff0703 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -11263,6 +11263,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)
@@ -11270,10 +11271,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.
@@ -11281,24 +11278,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 = {




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux