From nobody Fri Sep 25 16:50:51 2026 Received: from mta1.migadu.com (out-54.mta1.migadu.com [95.215.58.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2566C31195B for ; Thu, 10 Sep 2026 11:26:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039621; cv=none; b=DTRXLXf7Jf22GuPfU8qYxdt2yOtl2F7+KestymYGo5ZXx64rZO7dlyNiay8QspKGOjEjPUEMUCgyO0Fuo9Q4bCCR0Tf8f+HxUNhe9Y5s6oXaToGqmpp0eMHiHatgHKY6cM9y84Oqz2WdcWn1o7kwhAD+RzYQrtW8G7LmczggjDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039621; c=relaxed/simple; bh=95IyqXeqOZzjkj+0Ve1SI6MTNK+0O2yC9tCyVk1xeLI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pv3f6f1wVW/uu8InccRC0U/hiX3LwB0FPfi67PMGaFnD+tXQpmb/NI6/L26JIOJQDaNNmrhNzwBkeO+wZjwZM+xCaBRaeIdde4x6t2ODDevYUWqNbV7Wxi0YFWaZiixpx2j8Ei+YtxT8iBxCETG3b25d+KHVy5i8K/GrY2UwMck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=je5Ig+Al; arc=none smtp.client-ip=95.215.58.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="je5Ig+Al" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=95IyqXeqOZzjkj+0Ve1SI6MTNK+0O2yC9tCyVk1xeLI=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789039617; v=1; x=1789644417; b=je5Ig+AlXljzoKvBTJNFM7Ojb5Yzt/ic5puVMDQMyUl7NA6DhyHE/u+tbUnJvvpxr8XVPJQn Raz5FDzQFDLp+YNQilyleT83b5mDcXwFwfXt4pXRAzGzHWGTvQ78iVs6RmfeTE0aIm7JThT7sdz Cawdtw28tM8JSIi6USD2cM9c= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id cdfc5c82ce19bbc5; Thu, 10 Sep 2026 11:26:57 +0000 X-Mizu-Trace-ID: cdfc5c82ce19bbc5 X-Migadu-Flow: FLOW_OUT From: Jiayuan Chen To: bpf@vger.kernel.org Cc: Jiayuan Chen , Xiang Mei , Kuniyuki Iwashima , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Ihor Solodrai , John Fastabend , Stanislav Fomichev , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Neal Cardwell , Shuah Khan , Aditi Ghag , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH bpf v3 1/3] bpf: Fix out-of-bounds read of sk_protocol in bpf_sock_destroy() Date: Thu, 10 Sep 2026 19:26:26 +0800 Message-ID: <20260910112634.152195-1-jiayuan.chen@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910112107.148770-1-jiayuan.chen@linux.dev> References: <20260910112107.148770-1-jiayuan.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sk_protocol lives in struct sock, not in struct sock_common. A timewait or request sock handed to bpf_sock_destroy() by the tcp iterator is neither, so reading sk->sk_protocol runs past the object: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D BUG: KASAN: slab-out-of-bounds in bpf_sock_destroy+0xc7/0xe0 Read of size 2 at addr ffff8881047d11b4 by task test_progs/428 Tainted: [W]=3DWARN Call Trace: dump_stack_lvl+0x91/0xf0 print_report+0xd1/0x630 kasan_report+0xf3/0x130 __asan_report_load2_noabort+0x14/0x30 bpf_sock_destroy+0xc7/0xe0 bpf_prog_c3dd61f9d9cd9f37_iter_tcp6_timewait+0x9f/0xb7 bpf_iter_run_prog+0x538/0xde0 bpf_iter_tcp_seq_show+0x26b/0x4b0 bpf_seq_read+0x424/0x1210 vfs_read+0x197/0xe40 ksys_read+0x119/0x240 __x64_sys_read+0x72/0xc0 x64_sys_call+0x647/0x27e0 do_syscall_64+0xe5/0x610 entry_SYSCALL_64_after_hwframe+0x76/0x7e Only check sk_protocol on full socks. tcp_abort() already knows how to deal with TIME_WAIT and NEW_SYN_RECV socks. Also fix the comment, it never matched the code. Fixes: 4ddbcb886268 ("bpf: Add bpf_sock_destroy kfunc") Reported-by: Xiang Mei (Microsoft) Closes: https://lore.kernel.org/bpf/20260702224519.800135-1-xmei5@asu.edu/ Signed-off-by: Jiayuan Chen Reviewed-by: Kuniyuki Iwashima --- A reviewer asked to add ENOENT to the list of errors in the comment. I'd rather not list what the handlers return, that can change any time, so the comment now says "EOPNOTSUPP, or whatever the protocol specific destroy handler returns". A reviewer also worried that a sockmap iter could pass an unlocked sk here and run tcp_abort() without the sock lock. It cannot: only the tcp and udp iters mark their sk ctx arg as PTR_TRUSTED, and bpf_sock_destroy() needs a trusted arg. A sockmap iter prog calling it is rejected by the verifier with "R1 must be referenced or trusted", verified in qemu. v1 -> v2: modify comment AND avoid flaky about selftest v1: https://lore.kernel.org/bpf/20260903125306.299943-1-jiayuan.chen@linux.= dev/ --- net/core/filter.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index a043d179ff1ae..3e17ece09f028 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -12901,8 +12901,9 @@ __bpf_kfunc_start_defs(); * @sock: Pointer to socket to be destroyed * * Return: - * On error, may return EPROTONOSUPPORT, EINVAL. - * EPROTONOSUPPORT if protocol specific destroy handler is not supported. + * On error, may return EOPNOTSUPP, or whatever the protocol specific + * destroy handler returns. + * EOPNOTSUPP if protocol specific destroy handler is not supported. * 0 otherwise */ __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock) @@ -12914,8 +12915,12 @@ __bpf_kfunc int bpf_sock_destroy(struct sock_commo= n *sock) * Supporting protocols will need to acquire sock lock in the BPF context * prior to invoking this kfunc. */ - if (!sk->sk_prot->diag_destroy || (sk->sk_protocol !=3D IPPROTO_TCP && - sk->sk_protocol !=3D IPPROTO_UDP)) + if (!sk->sk_prot->diag_destroy) + return -EOPNOTSUPP; + + if (sk_fullsock(sk) && + sk->sk_protocol !=3D IPPROTO_TCP && + sk->sk_protocol !=3D IPPROTO_UDP) return -EOPNOTSUPP; =20 return sk->sk_prot->diag_destroy(sk, ECONNABORTED); --=20 2.43.0 From nobody Fri Sep 25 16:50:51 2026 Received: from mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E089472547 for ; Thu, 10 Sep 2026 11:27:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039674; cv=none; b=S1FDRIm1KZ15G7SSRQEaEmUr8LJGYElVhKIuP9XHoU54aBPWEWcuyK921yazigIOvQeq5vBD9StU+OcNfMKTNa0UWXXs0K882bFKjcCT8u2875xP554NBHsvI/3tny3rJMF8nu7m52qRSeD/QVcdxBd56w4KR5RThXrbIGYUEu8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039674; c=relaxed/simple; bh=XiIXkLh7xZJlvQ5cEZsGq8UI4ICTYL+iKbirY9wCMFU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pUhDKO9g1Trz54N8bZ3t5XiNTHWUz7c5bR5KJPy1v35wNFB1FEsQHBla69hUwWoqrAGW2FLcnr0qeL5RR6kJlIs9fWO8ALU2c5QrO4HqP4O++rOs2kYvi4flZ5s6yAlf13v6raNUnBABGPBX4cq9gB68PbxtJVwQsBEl8n0Tbfw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=XqMeqZ1f; arc=none smtp.client-ip=91.218.175.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="XqMeqZ1f" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=XiIXkLh7xZJlvQ5cEZsGq8UI4ICTYL+iKbirY9wCMFU=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789039669; v=1; x=1789644469; b=XqMeqZ1fWCnoFtEmEdPQKgg5d7Xwr/A4Yk/fn60Nsikh9iCXfdNC0o/ciC8ZUAwGUtFQld0j MGqRyL/Tz/8GgZcPPnj1XChd4/GJ1JPwz8oRH0k6FlDIvCGER7YJAiqq0sYKFs3BevyRIl9HFo6 cg2Uh1W0SNbEenhH3COmy2d4= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id c60bcde16ef5a46e; Thu, 10 Sep 2026 11:27:48 +0000 X-Mizu-Trace-ID: c60bcde16ef5a46e X-Migadu-Flow: FLOW_OUT From: Jiayuan Chen To: bpf@vger.kernel.org Cc: Jiayuan Chen , Daniel Borkmann , John Fastabend , Stanislav Fomichev , Martin KaFai Lau , Alexei Starovoitov , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Ihor Solodrai , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Neal Cardwell , Kuniyuki Iwashima , Shuah Khan , Aditi Ghag , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH bpf v3 2/3] tcp: Skip cond_resched() in inet_csk_listen_stop() under BPF context Date: Thu, 10 Sep 2026 19:27:28 +0800 Message-ID: <20260910112736.153710-1-jiayuan.chen@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910112107.148770-1-jiayuan.chen@linux.dev> References: <20260910112107.148770-1-jiayuan.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" bpf_sock_destroy() runs from the tcp iterator, under rcu_read_lock(). If the sock is a listener that still has children in its accept queue, tcp_abort() ends up in inet_csk_listen_stop() and the cond_resched() there trips the debug check: BUG: sleeping function called from invalid context at net/ipv4/inet_connect= ion_sock.c:1523 in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 628, name: test_progs preempt_count: 0, expected: 0 RCU nest depth: 1, expected: 0 locks held by test_progs/628: 3, last CPU#3: #0: ffff8881158cee18 (&p->lock){+.+.}-{4:4}, at: bpf_seq_read+0x56/0x1210 #1: ffff8881106bb858 (sk_lock-AF_INET6){+.+.}-{0:0}, at: bpf_iter_tcp_seq_= show+0x32b/0x4b0 #2: ffffffffb435af20 (rcu_read_lock){....}-{1:3}, at: bpf_iter_run_prog+0x= 46b/0xde0 CPU: 3 UID: 0 PID: 628 Comm: test_progs Tainted: G W 7.2.0= + #65 PREEMPT Tainted: [W]=3DWARN Call Trace: dump_stack_lvl+0xc1/0xf0 dump_stack+0x10/0x20 __might_resched+0x3d2/0x610 inet_csk_listen_stop+0x7b/0xbf0 tcp_abort+0x23b/0x3b0 bpf_sock_destroy+0xfc/0x140 bpf_prog_448133d24601754f_iter_tcp6_server+0x81/0x8a bpf_iter_run_prog+0x538/0xde0 bpf_iter_tcp_seq_show+0x26b/0x4b0 bpf_seq_read+0x424/0x1210 vfs_read+0x197/0xe40 ksys_read+0x119/0x240 __x64_sys_read+0x72/0xc0 x64_sys_call+0x647/0x27e0 do_syscall_64+0xe5/0x610 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7fad39b28aca RSP: 002b:00007ffc381c61c0 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 RAX: ffffffffffffffda RBX: 00007ffc381c6a88 RCX: 00007fad39b28aca RDX: 0000000000000032 RSI: 00007ffc381c6250 RDI: 0000000000000014 RBP: 00007ffc381c61e0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003 R13: 0000000000000000 R14: 000055f077c1bbb0 R15: 00007fad3a0f3000 The commit that added the kfunc already guards lock_sock() in tcp_abort() and udp_abort() with has_current_bpf_ctx(), but missed the listener path. Do the same for the cond_resched(). The loop runs inside the iterator's rcu_read_lock(), it must not reschedule or report a quiescent state there. Fixes: 4ddbcb886268 ("bpf: Add bpf_sock_destroy kfunc") Signed-off-by: Jiayuan Chen --- A reviewer worried that skipping cond_resched() lets a big accept queue run without a reschedule point under BPF. That can't be helped, the iterator runs the prog under rcu_read_lock() and rescheduling there is not an option. The loop is bounded by the accept queue. The iterator taking lock_sock() on a not yet accepted child while the listener is closed concurrently is a pre-existing issue with its own report, handled separately: https://lore.kernel.org/netdev/20260807095707.224300-1-zirajs7@gmail.com/ Kuniyuki suggested to just remove the cond_resched(), since after commit 7dadeaa6e851 ("sched: Further restrict the preemption modes") x86 and friends only have full and lazy preemption left. But VOLUNTARY is still there on arm, mips, sparc and others, NONE on alpha, hexagon and m68k, and this fix goes to stable where x86 has them too. close() on a big listener still relies on this cond_resched() there, so keep it and only skip it under BPF. It may be removed in the future once those modes are gone. --- net/ipv4/inet_connection_sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_soc= k.c index 6257459bcee24..6a30f11384547 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -1520,7 +1520,8 @@ void inet_csk_listen_stop(struct sock *sk) local_bh_enable(); sock_put(child); =20 - cond_resched(); + if (!has_current_bpf_ctx()) + cond_resched(); } if (queue->fastopenq.rskq_rst_head) { /* Free all the reqs queued in rskq_rst_head. */ --=20 2.43.0 From nobody Fri Sep 25 16:50:51 2026 Received: from mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C090C471D02 for ; Thu, 10 Sep 2026 11:28:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039716; cv=none; b=Q5SEaD3t5oeA7SFauVo/7cMUtJ2a34zyMviP9p0kxJzJxc0NdD7LJtSEt45nQNN1gC7B6xkq96w6uv5QgTjH0BmOUUFIjpx2HFPYRVhabzAt1ruEPPe26W3nsERfm8oJaGQv0t+enthgnisJVn5TdIa+Q1pPCpEQcsN61nFjQ4s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789039716; c=relaxed/simple; bh=hqlLi6bTP/oiCg2WQijATvjJsdlPO5fSQ16lKd07OH4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CtBz2ttUt35dcEbvT3WHNhgoN+K03et2aGvqwYpuxwMGMUcfR4Uyu033FK278X2/XFdZl+2BXrR3QrrTErX0rMJ+oyDrRn3H5znjtsQEs7YYiaF6B0pOYkrnp2zO2sDTDU21OTs/tDxyhr7uMnFp1kQNqsH2aGwTehCmaxI8n3A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=iBldzKJv; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="iBldzKJv" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=hqlLi6bTP/oiCg2WQijATvjJsdlPO5fSQ16lKd07OH4=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789039709; v=1; x=1789644509; b=iBldzKJv63L9xfzjR+b1R1usEB/qUW4nd9FRnzevBGFBrXFKg1AByFmhr0mvvRFZTL5vGksu jehtENo8lDeSR7vwQTTzYZY32MWaZy2dp9xppMgEXQVIwT27qgfG1K3TAlIgVbaZ4pVu6ox28e2 ICt9KTOJlWd0gNqzymN0dURo= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id e46b3dd9f2c8c11f; Thu, 10 Sep 2026 11:28:28 +0000 X-Mizu-Trace-ID: e46b3dd9f2c8c11f X-Migadu-Flow: FLOW_OUT From: Jiayuan Chen To: bpf@vger.kernel.org Cc: Jiayuan Chen , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Ihor Solodrai , John Fastabend , Stanislav Fomichev , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Neal Cardwell , Kuniyuki Iwashima , Shuah Khan , Aditi Ghag , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH bpf v3 3/3] selftests/bpf: Test bpf_sock_destroy() on TIME_WAIT and listener socks Date: Thu, 10 Sep 2026 19:28:02 +0800 Message-ID: <20260910112810.153801-1-jiayuan.chen@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910112107.148770-1-jiayuan.chen@linux.dev> References: <20260910112107.148770-1-jiayuan.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add two subtests. tcp_timewait: the client shuts down first and the server closes after it, so the client sock ends up in TIME_WAIT. A tcp iterator then finds the timewait sock by the cookie it inherited from the client sock and destroys it. Iterate once more to make sure it is gone. Without the first fix bpf_sock_destroy() reads past the timewait sock and KASAN complains. tcp_listen_pending: connect to a listener but never accept, so the child sits in the accept queue, then destroy the listener. Without the second fix the cond_resched() in inet_csk_listen_stop() trips the might_sleep check under rcu_read_lock(). ./test_progs -a sock_destroy #444/1 sock_destroy/tcp_client:OK #444/2 sock_destroy/tcp_server:OK #444/3 sock_destroy/tcp_listen_pending:OK #444/4 sock_destroy/tcp_timewait:OK #444/5 sock_destroy/udp_client:OK #444/6 sock_destroy/udp_server:OK #444/7 sock_destroy/trace_tcp_destroy_sock:OK #444 sock_destroy:OK Summary: 1/7 PASSED, 0 SKIPPED, 0/0 FAILED Signed-off-by: Jiayuan Chen --- .../selftests/bpf/prog_tests/sock_destroy.c | 121 ++++++++++++++++++ .../selftests/bpf/progs/sock_destroy_prog.c | 30 +++++ 2 files changed, 151 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c b/tools/= testing/selftests/bpf/prog_tests/sock_destroy.c index 9c11938fe597d..78d642a02bdb6 100644 --- a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c +++ b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include =20 @@ -110,6 +111,122 @@ static void test_tcp_server(struct sock_destroy_prog = *skel) close(serv); } =20 +static void test_tcp_listen_pending(struct sock_destroy_prog *skel) +{ + int serv =3D -1, clien =3D -1, accept_serv =3D -1, n, serv_port; + struct pollfd pfd =3D { .events =3D POLLIN }; + char buf[1]; + + serv =3D start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0); + if (!ASSERT_GE(serv, 0, "start_server")) + goto cleanup; + serv_port =3D get_socket_local_port(serv); + if (!ASSERT_GE(serv_port, 0, "get_sock_local_port")) + goto cleanup; + skel->bss->serv_port =3D (__be16)serv_port; + + /* + * Connect but never accept, so the child sits in the accept queue + * of the listener. Wait until it's actually there. + */ + clien =3D connect_to_fd(serv, 0); + if (!ASSERT_GE(clien, 0, "connect_to_fd")) + goto cleanup; + pfd.fd =3D serv; + if (!ASSERT_EQ(poll(&pfd, 1, -1), 1, "poll listener")) + goto cleanup; + + /* Run iterator program that destroys server sockets. */ + start_iter_sockets(skel->progs.iter_tcp6_server); + + accept_serv =3D accept(serv, NULL, NULL); + if (!ASSERT_LT(accept_serv, 0, "accept on destroyed listener")) + goto cleanup; + ASSERT_EQ(errno, EINVAL, "error code on destroyed listener"); + + /* The unaccepted child was reset along with the listener. */ + n =3D recv(clien, buf, sizeof(buf), 0); + if (!ASSERT_LT(n, 0, "client recv on reset child")) + goto cleanup; + ASSERT_EQ(errno, ECONNRESET, "error code on reset child"); + +cleanup: + if (clien !=3D -1) + close(clien); + if (accept_serv !=3D -1) + close(accept_serv); + if (serv !=3D -1) + close(serv); +} + +static void test_tcp_timewait(struct sock_destroy_prog *skel) +{ + int serv =3D -1, clien =3D -1, accept_serv =3D -1, n; + struct timeval tv =3D {}; + char buf[1]; + + serv =3D start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0); + if (!ASSERT_GE(serv, 0, "start_server")) + goto cleanup; + + clien =3D connect_to_fd(serv, 0); + if (!ASSERT_GE(clien, 0, "connect_to_fd")) + goto cleanup; + + accept_serv =3D accept(serv, NULL, NULL); + if (!ASSERT_GE(accept_serv, 0, "serv accept")) + goto cleanup; + + /* + * Active close from the client, then close the server side. Once + * recv() sees EOF the server FIN has been processed and the client + * sock is in TIME_WAIT. Block without timeout so a loaded CI box + * can't race us. + */ + if (!ASSERT_OK(setsockopt(clien, SOL_SOCKET, SO_RCVTIMEO, &tv, + sizeof(tv)), "clear rcvtimeo")) + goto cleanup; + if (!ASSERT_OK(shutdown(clien, SHUT_WR), "client shutdown")) + goto cleanup; + + /* + * Make sure the server has seen the client FIN before it closes, + * so the two FINs never cross. + */ + n =3D recv(accept_serv, buf, sizeof(buf), 0); + if (!ASSERT_EQ(n, 0, "server recv EOF")) + goto cleanup; + + close(accept_serv); + accept_serv =3D -1; + + /* block until return EOF */ + n =3D recv(clien, buf, sizeof(buf), 0); + if (!ASSERT_EQ(n, 0, "client recv EOF")) + goto cleanup; + + /* Run iterator program that destroys the timewait client sock. */ + skel->bss->tw_found =3D 0; + start_iter_sockets(skel->progs.iter_tcp6_timewait); + if (!ASSERT_EQ(skel->bss->tw_found, 1, "timewait sock found")) + goto cleanup; + + ASSERT_OK(skel->bss->tw_destroy_err, "destroy timewait sock"); + + /* The destroyed timewait sock must be gone. */ + skel->bss->tw_found =3D 0; + start_iter_sockets(skel->progs.iter_tcp6_timewait); + ASSERT_EQ(skel->bss->tw_found, 0, "timewait sock destroyed"); + +cleanup: + if (clien !=3D -1) + close(clien); + if (accept_serv !=3D -1) + close(accept_serv); + if (serv !=3D -1) + close(serv); +} + static void test_udp_client(struct sock_destroy_prog *skel) { int serv =3D -1, clien =3D -1, n =3D 0; @@ -204,6 +321,10 @@ void test_sock_destroy(void) test_tcp_client(skel); if (test__start_subtest("tcp_server")) test_tcp_server(skel); + if (test__start_subtest("tcp_listen_pending")) + test_tcp_listen_pending(skel); + if (test__start_subtest("tcp_timewait")) + test_tcp_timewait(skel); if (test__start_subtest("udp_client")) test_udp_client(skel); if (test__start_subtest("udp_server")) diff --git a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c b/tools/= testing/selftests/bpf/progs/sock_destroy_prog.c index 9e0bf7a54cec9..0a8887543218a 100644 --- a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c +++ b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c @@ -7,6 +7,8 @@ #include "bpf_tracing_net.h" =20 __be16 serv_port =3D 0; +int tw_found =3D 0; +int tw_destroy_err =3D 0; =20 int bpf_sock_destroy(struct sock_common *sk) __ksym; =20 @@ -100,6 +102,34 @@ int iter_tcp6_server(struct bpf_iter__tcp *ctx) return 0; } =20 +SEC("iter/tcp") +int iter_tcp6_timewait(struct bpf_iter__tcp *ctx) +{ + struct sock_common *sk_common =3D ctx->sk_common; + __u64 *val; + int key =3D 0; + + if (!sk_common) + return 0; + + if (sk_common->skc_family !=3D AF_INET6) + return 0; + + if (!bpf_skc_to_tcp_timewait_sock(sk_common)) + return 0; + + val =3D bpf_map_lookup_elem(&tcp_conn_sockets, &key); + if (!val) + return 0; + /* The timewait sock inherits the cookie of the closed client sock. */ + if (bpf_get_socket_cookie(sk_common) !=3D *val) + return 0; + + tw_found++; + tw_destroy_err =3D bpf_sock_destroy(sk_common); + + return 0; +} =20 SEC("iter/udp") int iter_udp6_client(struct bpf_iter__udp *ctx) --=20 2.43.0