Skip to content

Commit 7c96d51

Browse files
Paolo Abenigregkh
authored andcommitted
mptcp: plug races between subflow fail and subflow creation
commit def5b7b upstream. We have races similar to the one addressed by the previous patch between subflow failing and additional subflow creation. They are just harder to trigger. The solution is similar. Use a separate flag to track the condition 'socket state prevent any additional subflow creation' protected by the fallback lock. The socket fallback makes such flag true, and also receiving or sending an MP_FAIL option. The field 'allow_infinite_fallback' is now always touched under the relevant lock, we can drop the ONCE annotation on write. Fixes: 478d770 ("mptcp: send out MP_FAIL when data checksum fails") Cc: stable@vger.kernel.org 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/20250714-net-mptcp-fallback-races-v1-2-391aff963322@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> [ Conflicts in subflow.c, because commit f1f2651 ("mptcp: use plain bool instead of custom binary enum") and commit 46a5d3a ("mptcp: fix typos in comments") are not in this version. Both are causing conflicts in the context, and the same modifications can still be applied. ] Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 75a4c9a commit 7c96d51

4 files changed

Lines changed: 32 additions & 13 deletions

File tree

net/mptcp/pm.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,14 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
304304

305305
pr_debug("fail_seq=%llu\n", fail_seq);
306306

307-
if (!READ_ONCE(msk->allow_infinite_fallback))
307+
/* After accepting the fail, we can't create any other subflows */
308+
spin_lock_bh(&msk->fallback_lock);
309+
if (!msk->allow_infinite_fallback) {
310+
spin_unlock_bh(&msk->fallback_lock);
308311
return;
312+
}
313+
msk->allow_subflows = false;
314+
spin_unlock_bh(&msk->fallback_lock);
309315

310316
if (!subflow->fail_tout) {
311317
pr_debug("send MP_FAIL response and infinite map\n");

net/mptcp/protocol.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
875875
static void mptcp_subflow_joined(struct mptcp_sock *msk, struct sock *ssk)
876876
{
877877
mptcp_subflow_ctx(ssk)->map_seq = READ_ONCE(msk->ack_seq);
878-
WRITE_ONCE(msk->allow_infinite_fallback, false);
878+
msk->allow_infinite_fallback = false;
879879
mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC);
880880
}
881881

@@ -887,7 +887,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
887887
return false;
888888

889889
spin_lock_bh(&msk->fallback_lock);
890-
if (__mptcp_check_fallback(msk)) {
890+
if (!msk->allow_subflows) {
891891
spin_unlock_bh(&msk->fallback_lock);
892892
return false;
893893
}
@@ -2688,7 +2688,7 @@ static void __mptcp_retrans(struct sock *sk)
26882688
len = max(copied, len);
26892689
tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
26902690
info.size_goal);
2691-
WRITE_ONCE(msk->allow_infinite_fallback, false);
2691+
msk->allow_infinite_fallback = false;
26922692
}
26932693
spin_unlock_bh(&msk->fallback_lock);
26942694

@@ -2819,7 +2819,8 @@ static void __mptcp_init_sock(struct sock *sk)
28192819
WRITE_ONCE(msk->first, NULL);
28202820
inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
28212821
WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
2822-
WRITE_ONCE(msk->allow_infinite_fallback, true);
2822+
msk->allow_infinite_fallback = true;
2823+
msk->allow_subflows = true;
28232824
msk->recovery = false;
28242825
msk->subflow_id = 1;
28252826

@@ -3624,7 +3625,7 @@ bool mptcp_finish_join(struct sock *ssk)
36243625
/* active subflow, already present inside the conn_list */
36253626
if (!list_empty(&subflow->node)) {
36263627
spin_lock_bh(&msk->fallback_lock);
3627-
if (__mptcp_check_fallback(msk)) {
3628+
if (!msk->allow_subflows) {
36283629
spin_unlock_bh(&msk->fallback_lock);
36293630
return false;
36303631
}

net/mptcp/protocol.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,15 @@ struct mptcp_sock {
330330
u64 rtt_us; /* last maximum rtt of subflows */
331331
} rcvq_space;
332332
u8 scaling_ratio;
333+
bool allow_subflows;
333334

334335
u32 subflow_id;
335336
u32 setsockopt_seq;
336337
char ca_name[TCP_CA_NAME_MAX];
337338

338-
spinlock_t fallback_lock; /* protects fallback and
339-
* allow_infinite_fallback
339+
spinlock_t fallback_lock; /* protects fallback,
340+
* allow_infinite_fallback and
341+
* allow_join
340342
*/
341343
};
342344

@@ -1113,6 +1115,7 @@ static inline bool __mptcp_try_fallback(struct mptcp_sock *msk)
11131115
return false;
11141116
}
11151117

1118+
msk->allow_subflows = false;
11161119
set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
11171120
spin_unlock_bh(&msk->fallback_lock);
11181121
return true;

net/mptcp/subflow.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,20 +1257,29 @@ static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ss
12571257
mptcp_schedule_work(sk);
12581258
}
12591259

1260-
static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
1260+
static bool mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
12611261
{
12621262
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
12631263
unsigned long fail_tout;
12641264

1265+
/* we are really failing, prevent any later subflow join */
1266+
spin_lock_bh(&msk->fallback_lock);
1267+
if (!msk->allow_infinite_fallback) {
1268+
spin_unlock_bh(&msk->fallback_lock);
1269+
return false;
1270+
}
1271+
msk->allow_subflows = false;
1272+
spin_unlock_bh(&msk->fallback_lock);
1273+
12651274
/* greceful failure can happen only on the MPC subflow */
12661275
if (WARN_ON_ONCE(ssk != READ_ONCE(msk->first)))
1267-
return;
1276+
return false;
12681277

12691278
/* since the close timeout take precedence on the fail one,
12701279
* no need to start the latter when the first is already set
12711280
*/
12721281
if (sock_flag((struct sock *)msk, SOCK_DEAD))
1273-
return;
1282+
return true;
12741283

12751284
/* we don't need extreme accuracy here, use a zero fail_tout as special
12761285
* value meaning no fail timeout at all;
@@ -1282,6 +1291,7 @@ static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
12821291
tcp_send_ack(ssk);
12831292

12841293
mptcp_reset_tout_timer(msk, subflow->fail_tout);
1294+
return true;
12851295
}
12861296

12871297
static bool subflow_check_data_avail(struct sock *ssk)
@@ -1342,12 +1352,11 @@ static bool subflow_check_data_avail(struct sock *ssk)
13421352
(subflow->mp_join || subflow->valid_csum_seen)) {
13431353
subflow->send_mp_fail = 1;
13441354

1345-
if (!READ_ONCE(msk->allow_infinite_fallback)) {
1355+
if (!mptcp_subflow_fail(msk, ssk)) {
13461356
subflow->reset_transient = 0;
13471357
subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
13481358
goto reset;
13491359
}
1350-
mptcp_subflow_fail(msk, ssk);
13511360
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_DATA_AVAIL);
13521361
return true;
13531362
}

0 commit comments

Comments
 (0)