Skip to content

Commit

Permalink
mptcp: fix possible list corruption on passive MPJ
Browse files Browse the repository at this point in the history
At passive MPJ time, if the msk socket lock is held by the user,
the new subflow is appended to the msk->join_list under the msk
data lock.

In mptcp_release_cb()/__mptcp_flush_join_list(), the subflows in
that list are moved from the join_list into the conn_list under the
msk socket lock.

Append and removal could race, possibly corrupting such list.
Address the issue splicing the join list into a temporary one while
still under the msk data lock.

Found by code inspection, the race itself should be almost impossible
to trigger in practice.

Fixes: 3e50149 ("mptcp: cleanup MPJ subflow list handling")
Cc: [email protected]
Signed-off-by: Paolo Abeni <[email protected]>
Reviewed-by: Matthieu Baerts <[email protected]>
Signed-off-by: Matthieu Baerts <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
Paolo Abeni authored and kuba-moo committed Jun 22, 2023
1 parent 0ad529d commit 56a666c
Showing 1 changed file with 9 additions and 3 deletions.
12 changes: 9 additions & 3 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,12 +850,12 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
return true;
}

static void __mptcp_flush_join_list(struct sock *sk)
static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list)
{
struct mptcp_subflow_context *tmp, *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);

list_for_each_entry_safe(subflow, tmp, &msk->join_list, node) {
list_for_each_entry_safe(subflow, tmp, join_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
bool slow = lock_sock_fast(ssk);

Expand Down Expand Up @@ -3342,9 +3342,14 @@ static void mptcp_release_cb(struct sock *sk)
for (;;) {
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
msk->push_pending;
struct list_head join_list;

if (!flags)
break;

INIT_LIST_HEAD(&join_list);
list_splice_init(&msk->join_list, &join_list);

/* the following actions acquire the subflow socket lock
*
* 1) can't be invoked in atomic scope
Expand All @@ -3355,8 +3360,9 @@ static void mptcp_release_cb(struct sock *sk)
msk->push_pending = 0;
msk->cb_flags &= ~flags;
spin_unlock_bh(&sk->sk_lock.slock);

if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
__mptcp_flush_join_list(sk);
__mptcp_flush_join_list(sk, &join_list);
if (flags & BIT(MPTCP_PUSH_PENDING))
__mptcp_push_pending(sk, 0);
if (flags & BIT(MPTCP_RETRANSMIT))
Expand Down

0 comments on commit 56a666c

Please sign in to comment.