Skip to content

Commit 499ada5

Browse files
Paolo Abenidavem330
authored andcommitted
mptcp: fix soft lookup in subflow_error_report()
Maxim reported a soft lookup in subflow_error_report(): watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [swapper/0:0] RIP: 0010:native_queued_spin_lock_slowpath RSP: 0018:ffffa859c0003bc0 EFLAGS: 00000202 RAX: 0000000000000101 RBX: 0000000000000001 RCX: 0000000000000000 RDX: ffff9195c2772d88 RSI: 0000000000000000 RDI: ffff9195c2772d88 RBP: ffff9195c2772d00 R08: 00000000000067b0 R09: c6e31da9eb1e44f4 R10: ffff9195ef379700 R11: ffff9195edb50710 R12: ffff9195c2772d88 R13: ffff9195f500e3d0 R14: ffff9195ef379700 R15: ffff9195ef379700 FS: 0000000000000000(0000) GS:ffff91961f400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000c000407000 CR3: 0000000002988000 CR4: 00000000000006f0 Call Trace: <IRQ> _raw_spin_lock_bh subflow_error_report mptcp_subflow_data_available __mptcp_move_skbs_from_subflow mptcp_data_ready tcp_data_queue tcp_rcv_established tcp_v4_do_rcv tcp_v4_rcv ip_protocol_deliver_rcu ip_local_deliver_finish __netif_receive_skb_one_core netif_receive_skb rtl8139_poll 8139too __napi_poll net_rx_action __do_softirq __irq_exit_rcu common_interrupt </IRQ> The calling function - mptcp_subflow_data_available() - can be invoked from different contexts: - plain ssk socket lock - ssk socket lock + mptcp_data_lock - ssk socket lock + mptcp_data_lock + msk socket lock. Since subflow_error_report() tries to acquire the mptcp_data_lock, the latter two call chains will cause soft lookup. This change addresses the issue moving the error reporting call to outer functions, where the held locks list is known and the we can acquire only the needed one. Reported-by: Maxim Galaganov <[email protected]> Fixes: 15cc104 ("mptcp: deliver ssk errors to msk") Closes: multipath-tcp/mptcp_net-next#199 Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2395da0 commit 499ada5

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

net/mptcp/protocol.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,12 @@ static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)
680680

681681
__mptcp_move_skbs_from_subflow(msk, ssk, &moved);
682682
__mptcp_ofo_queue(msk);
683+
if (unlikely(ssk->sk_err)) {
684+
if (!sock_owned_by_user(sk))
685+
__mptcp_error_report(sk);
686+
else
687+
set_bit(MPTCP_ERROR_REPORT, &msk->flags);
688+
}
683689

684690
/* If the moves have caught up with the DATA_FIN sequence number
685691
* it's time to ack the DATA_FIN and change socket state, but
@@ -1948,6 +1954,9 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
19481954
done = __mptcp_move_skbs_from_subflow(msk, ssk, &moved);
19491955
mptcp_data_unlock(sk);
19501956
tcp_cleanup_rbuf(ssk, moved);
1957+
1958+
if (unlikely(ssk->sk_err))
1959+
__mptcp_error_report(sk);
19511960
unlock_sock_fast(ssk, slowpath);
19521961
} while (!done);
19531962

net/mptcp/subflow.c

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,6 @@ static bool subflow_check_data_avail(struct sock *ssk)
10601060
* subflow_error_report() will introduce the appropriate barriers
10611061
*/
10621062
ssk->sk_err = EBADMSG;
1063-
ssk->sk_error_report(ssk);
10641063
tcp_set_state(ssk, TCP_CLOSE);
10651064
subflow->reset_transient = 0;
10661065
subflow->reset_reason = MPTCP_RST_EMPTCP;
@@ -1115,41 +1114,6 @@ void mptcp_space(const struct sock *ssk, int *space, int *full_space)
11151114
*full_space = tcp_full_space(sk);
11161115
}
11171116

1118-
static void subflow_data_ready(struct sock *sk)
1119-
{
1120-
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
1121-
u16 state = 1 << inet_sk_state_load(sk);
1122-
struct sock *parent = subflow->conn;
1123-
struct mptcp_sock *msk;
1124-
1125-
msk = mptcp_sk(parent);
1126-
if (state & TCPF_LISTEN) {
1127-
/* MPJ subflow are removed from accept queue before reaching here,
1128-
* avoid stray wakeups
1129-
*/
1130-
if (reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue))
1131-
return;
1132-
1133-
set_bit(MPTCP_DATA_READY, &msk->flags);
1134-
parent->sk_data_ready(parent);
1135-
return;
1136-
}
1137-
1138-
WARN_ON_ONCE(!__mptcp_check_fallback(msk) && !subflow->mp_capable &&
1139-
!subflow->mp_join && !(state & TCPF_CLOSE));
1140-
1141-
if (mptcp_subflow_data_available(sk))
1142-
mptcp_data_ready(parent, sk);
1143-
}
1144-
1145-
static void subflow_write_space(struct sock *ssk)
1146-
{
1147-
struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
1148-
1149-
mptcp_propagate_sndbuf(sk, ssk);
1150-
mptcp_write_space(sk);
1151-
}
1152-
11531117
void __mptcp_error_report(struct sock *sk)
11541118
{
11551119
struct mptcp_subflow_context *subflow;
@@ -1190,6 +1154,43 @@ static void subflow_error_report(struct sock *ssk)
11901154
mptcp_data_unlock(sk);
11911155
}
11921156

1157+
static void subflow_data_ready(struct sock *sk)
1158+
{
1159+
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
1160+
u16 state = 1 << inet_sk_state_load(sk);
1161+
struct sock *parent = subflow->conn;
1162+
struct mptcp_sock *msk;
1163+
1164+
msk = mptcp_sk(parent);
1165+
if (state & TCPF_LISTEN) {
1166+
/* MPJ subflow are removed from accept queue before reaching here,
1167+
* avoid stray wakeups
1168+
*/
1169+
if (reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue))
1170+
return;
1171+
1172+
set_bit(MPTCP_DATA_READY, &msk->flags);
1173+
parent->sk_data_ready(parent);
1174+
return;
1175+
}
1176+
1177+
WARN_ON_ONCE(!__mptcp_check_fallback(msk) && !subflow->mp_capable &&
1178+
!subflow->mp_join && !(state & TCPF_CLOSE));
1179+
1180+
if (mptcp_subflow_data_available(sk))
1181+
mptcp_data_ready(parent, sk);
1182+
else if (unlikely(sk->sk_err))
1183+
subflow_error_report(sk);
1184+
}
1185+
1186+
static void subflow_write_space(struct sock *ssk)
1187+
{
1188+
struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
1189+
1190+
mptcp_propagate_sndbuf(sk, ssk);
1191+
mptcp_write_space(sk);
1192+
}
1193+
11931194
static struct inet_connection_sock_af_ops *
11941195
subflow_default_af_ops(struct sock *sk)
11951196
{
@@ -1500,6 +1501,8 @@ static void subflow_state_change(struct sock *sk)
15001501
*/
15011502
if (mptcp_subflow_data_available(sk))
15021503
mptcp_data_ready(parent, sk);
1504+
else if (unlikely(sk->sk_err))
1505+
subflow_error_report(sk);
15031506

15041507
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
15051508

0 commit comments

Comments
 (0)