Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mptcp: fix soft lockup in mptcp_recvmsg()

syzbot reported a soft lockup in mptcp_recvmsg() [0].

When receiving data with MSG_PEEK | MSG_WAITALL flags, the skb is not
removed from the sk_receive_queue. This causes sk_wait_data() to always
find available data and never perform actual waiting, leading to a soft
lockup.

Fix this by adding a 'last' parameter to track the last peeked skb.
This allows sk_wait_data() to make informed waiting decisions and prevent
infinite loops when MSG_PEEK is used.

[0]:
watchdog: BUG: soft lockup - CPU#2 stuck for 156s! [server:1963]
Modules linked in:
CPU: 2 UID: 0 PID: 1963 Comm: server Not tainted 6.19.0-rc8 #61 PREEMPT(none)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:sk_wait_data+0x15/0x190
Code: 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 41 56 41 55 41 54 49 89 f4 55 48 89 d5 53 48 89 fb <48> 83 ec 30 65 48 8b 05 17 a4 6b 01 48 89 44 24 28 31 c0 65 48 8b
RSP: 0018:ffffc90000603ca0 EFLAGS: 00000246
RAX: 0000000000000000 RBX: ffff888102bf0800 RCX: 0000000000000001
RDX: 0000000000000000 RSI: ffffc90000603d18 RDI: ffff888102bf0800
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000000101
R10: 0000000000000000 R11: 0000000000000075 R12: ffffc90000603d18
R13: ffff888102bf0800 R14: ffff888102bf0800 R15: 0000000000000000
FS: 00007f6e38b8c4c0(0000) GS:ffff8881b877e000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055aa7bff1680 CR3: 0000000105cbe000 CR4: 00000000000006f0
Call Trace:
<TASK>
mptcp_recvmsg+0x547/0x8c0 net/mptcp/protocol.c:2329
inet_recvmsg+0x11f/0x130 net/ipv4/af_inet.c:891
sock_recvmsg+0x94/0xc0 net/socket.c:1100
__sys_recvfrom+0xb2/0x130 net/socket.c:2256
__x64_sys_recvfrom+0x1f/0x30 net/socket.c:2267
do_syscall_64+0x59/0x2d0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x76/0x7e arch/x86/entry/entry_64.S:131
RIP: 0033:0x7f6e386a4a1d
Code: 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 8d 05 f1 de 2c 00 41 89 ca 8b 00 85 c0 75 20 45 31 c9 45 31 c0 b8 2d 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 6b f3 c3 66 0f 1f 84 00 00 00 00 00 41 56 41
RSP: 002b:00007ffc3c4bb078 EFLAGS: 00000246 ORIG_RAX: 000000000000002d
RAX: ffffffffffffffda RBX: 000000000000861e RCX: 00007f6e386a4a1d
RDX: 00000000000003ff RSI: 00007ffc3c4bb150 RDI: 0000000000000004
RBP: 00007ffc3c4bb570 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000103 R11: 0000000000000246 R12: 00005605dbc00be0
R13: 00007ffc3c4bb650 R14: 0000000000000000 R15: 0000000000000000
</TASK>

Fixes: 8e04ce45a8db ("mptcp: fix MSG_PEEK stream corruption")
Signed-off-by: Li Xiasong <lixiasong1@huawei.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20260330120335.659027-1-lixiasong1@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Li Xiasong and committed by
Jakub Kicinski
5dd8025a 9ca562bb

+8 -3
+8 -3
net/mptcp/protocol.c
··· 2006 2006 static int __mptcp_recvmsg_mskq(struct sock *sk, struct msghdr *msg, 2007 2007 size_t len, int flags, int copied_total, 2008 2008 struct scm_timestamping_internal *tss, 2009 - int *cmsg_flags) 2009 + int *cmsg_flags, struct sk_buff **last) 2010 2010 { 2011 2011 struct mptcp_sock *msk = mptcp_sk(sk); 2012 2012 struct sk_buff *skb, *tmp; ··· 2023 2023 /* skip already peeked skbs */ 2024 2024 if (total_data_len + data_len <= copied_total) { 2025 2025 total_data_len += data_len; 2026 + *last = skb; 2026 2027 continue; 2027 2028 } 2028 2029 ··· 2059 2058 } 2060 2059 2061 2060 mptcp_eat_recv_skb(sk, skb); 2061 + } else { 2062 + *last = skb; 2062 2063 } 2063 2064 2064 2065 if (copied >= len) ··· 2291 2288 cmsg_flags = MPTCP_CMSG_INQ; 2292 2289 2293 2290 while (copied < len) { 2291 + struct sk_buff *last = NULL; 2294 2292 int err, bytes_read; 2295 2293 2296 2294 bytes_read = __mptcp_recvmsg_mskq(sk, msg, len - copied, flags, 2297 - copied, &tss, &cmsg_flags); 2295 + copied, &tss, &cmsg_flags, 2296 + &last); 2298 2297 if (unlikely(bytes_read < 0)) { 2299 2298 if (!copied) 2300 2299 copied = bytes_read; ··· 2348 2343 2349 2344 pr_debug("block timeout %ld\n", timeo); 2350 2345 mptcp_cleanup_rbuf(msk, copied); 2351 - err = sk_wait_data(sk, &timeo, NULL); 2346 + err = sk_wait_data(sk, &timeo, last); 2352 2347 if (err < 0) { 2353 2348 err = copied ? : err; 2354 2349 goto out_err;