mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00:00
mptcp: fix possible list corruption on passive MPJ
commit56a666c48b
upstream. 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:
parent
b747e75598
commit
1d31275426
1 changed files with 9 additions and 3 deletions
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue