mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
mptcp: fix possible list corruption on passive MPJ
commit56a666c48bupstream. 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:3e5014909b("mptcp: cleanup MPJ subflow list handling") Cc: stable@vger.kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
b747e75598
commit
1d31275426
@@ -846,12 +846,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);
|
||||
|
||||
@@ -3335,9 +3335,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
|
||||
@@ -3348,8 +3353,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))
|
||||
|
||||
Reference in New Issue
Block a user