Skip to content

Commit 79f80a7

Browse files
Paolo Abenigregkh
authored andcommitted
mptcp: fallback earlier on simult connection
[ Upstream commit 71154bb ] Syzkaller reports a simult-connect race leading to inconsistent fallback status: WARNING: CPU: 3 PID: 33 at net/mptcp/subflow.c:1515 subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Modules linked in: CPU: 3 UID: 0 PID: 33 Comm: ksoftirqd/3 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Code: 89 ee e8 78 61 3c f6 40 84 ed 75 21 e8 8e 66 3c f6 44 89 fe bf 07 00 00 00 e8 c1 61 3c f6 41 83 ff 07 74 09 e8 76 66 3c f6 90 <0f> 0b 90 e8 6d 66 3c f6 48 89 df e8 e5 ad ff ff 31 ff 89 c5 89 c6 RSP: 0018:ffffc900006cf338 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff888031acd100 RCX: ffffffff8b7f2abf RDX: ffff88801e6ea440 RSI: ffffffff8b7f2aca RDI: 0000000000000005 RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007 R10: 0000000000000004 R11: 0000000000002c10 R12: ffff88802ba69900 R13: 1ffff920000d9e67 R14: ffff888046f81800 R15: 0000000000000004 FS: 0000000000000000(0000) GS:ffff8880d69bc000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000560fc0ca1670 CR3: 0000000032c3a000 CR4: 0000000000352ef0 Call Trace: <TASK> tcp_data_queue+0x13b0/0x4f90 net/ipv4/tcp_input.c:5197 tcp_rcv_state_process+0xfdf/0x4ec0 net/ipv4/tcp_input.c:6922 tcp_v6_do_rcv+0x492/0x1740 net/ipv6/tcp_ipv6.c:1672 tcp_v6_rcv+0x2976/0x41e0 net/ipv6/tcp_ipv6.c:1918 ip6_protocol_deliver_rcu+0x188/0x1520 net/ipv6/ip6_input.c:438 ip6_input_finish+0x1e4/0x4b0 net/ipv6/ip6_input.c:489 NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ip6_input+0x105/0x2f0 net/ipv6/ip6_input.c:500 dst_input include/net/dst.h:471 [inline] ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ipv6_rcv+0x264/0x650 net/ipv6/ip6_input.c:311 __netif_receive_skb_one_core+0x12d/0x1e0 net/core/dev.c:5979 __netif_receive_skb+0x1d/0x160 net/core/dev.c:6092 process_backlog+0x442/0x15e0 net/core/dev.c:6444 __napi_poll.constprop.0+0xba/0x550 net/core/dev.c:7494 napi_poll net/core/dev.c:7557 [inline] net_rx_action+0xa9f/0xfe0 net/core/dev.c:7684 handle_softirqs+0x216/0x8e0 kernel/softirq.c:579 run_ksoftirqd kernel/softirq.c:968 [inline] run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960 smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:160 kthread+0x3c2/0x780 kernel/kthread.c:463 ret_from_fork+0x5d7/0x6f0 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK> The TCP subflow can process the simult-connect syn-ack packet after transitioning to TCP_FIN1 state, bypassing the MPTCP fallback check, as the sk_state_change() callback is not invoked for * -> FIN_WAIT1 transitions. That will move the msk socket to an inconsistent status and the next incoming data will hit the reported splat. Close the race moving the simult-fallback check at the earliest possible stage - that is at syn-ack generation time. About the fixes tags: [2] was supposed to also fix this issue introduced by [3]. [1] is required as a dependence: it was not explicitly marked as a fix, but it is one and it has already been backported before [3]. In other words, this commit should be backported up to [3], including [2] and [1] if that's not already there. Fixes: 23e89e8 ("tcp: Don't drop SYN+ACK for simultaneous connect().") [1] Fixes: 4fd19a3 ("mptcp: fix inconsistent state on fastopen race") [2] Fixes: 1e777f3 ("mptcp: add MSG_FASTOPEN sendmsg flag support") [3] Cc: stable@vger.kernel.org Reported-by: syzbot+0ff6b771b4f7a5bce83b@syzkaller.appspotmail.com Closes: multipath-tcp/mptcp_net-next#586 Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Link: https://patch.msgid.link/20251212-net-mptcp-subflow_data_ready-warn-v1-1-d1f9fd1c36c8@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com> [ adapted mptcp_try_fallback() call ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1a4a724 commit 79f80a7

3 files changed

Lines changed: 13 additions & 13 deletions

File tree

net/mptcp/options.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
408408
*/
409409
subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
410410
if (subflow->request_mptcp) {
411+
if (unlikely(subflow_simultaneous_connect(sk))) {
412+
WARN_ON_ONCE(!mptcp_try_fallback(sk));
413+
414+
/* Ensure mptcp_finish_connect() will not process the
415+
* MPC handshake.
416+
*/
417+
subflow->request_mptcp = 0;
418+
return false;
419+
}
420+
411421
opts->suboptions = OPTION_MPTCP_MPC_SYN;
412422
opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk));
413423
opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));

net/mptcp/protocol.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,10 +1283,8 @@ static inline bool subflow_simultaneous_connect(struct sock *sk)
12831283
{
12841284
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
12851285

1286-
return (1 << sk->sk_state) &
1287-
(TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) &&
1288-
is_active_ssk(subflow) &&
1289-
!subflow->conn_finished;
1286+
/* Note that the sk state implies !subflow->conn_finished. */
1287+
return sk->sk_state == TCP_SYN_RECV && is_active_ssk(subflow);
12901288
}
12911289

12921290
#ifdef CONFIG_SYN_COOKIES

net/mptcp/subflow.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,18 +1848,10 @@ static void subflow_state_change(struct sock *sk)
18481848
{
18491849
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
18501850
struct sock *parent = subflow->conn;
1851-
struct mptcp_sock *msk;
1851+
struct mptcp_sock *msk = mptcp_sk(parent);
18521852

18531853
__subflow_state_change(sk);
18541854

1855-
msk = mptcp_sk(parent);
1856-
if (subflow_simultaneous_connect(sk)) {
1857-
WARN_ON_ONCE(!mptcp_try_fallback(sk));
1858-
pr_fallback(msk);
1859-
subflow->conn_finished = 1;
1860-
mptcp_propagate_state(parent, sk, subflow, NULL);
1861-
}
1862-
18631855
/* as recvmsg() does not acquire the subflow socket for ssk selection
18641856
* a fin packet carrying a DSS can be unnoticed if we don't trigger
18651857
* the data available machinery here.

0 commit comments

Comments
 (0)