Skip to content

Commit 6aeed90

Browse files
Paolo Abenikuba-moo
Paolo Abeni
authored andcommitted
mptcp: fix race on unaccepted mptcp sockets
When the listener socket owning the relevant request is closed, it frees the unaccepted subflows and that causes later deletion of the paired MPTCP sockets. The mptcp socket's worker can run in the time interval between such delete operations. When that happens, any access to msk->first will cause an UaF access, as the subflow cleanup did not cleared such field in the mptcp socket. Address the issue explicitly traversing the listener socket accept queue at close time and performing the needed cleanup on the pending msk. Note that the locking is a bit tricky, as we need to acquire the msk socket lock, while still owning the subflow socket one. Fixes: 86e39e0 ("mptcp: keep track of local endpoint still available for each msk") Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f745a3e commit 6aeed90

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

net/mptcp/protocol.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
23312331
kfree_rcu(subflow, rcu);
23322332
} else {
23332333
/* otherwise tcp will dispose of the ssk and subflow ctx */
2334+
if (ssk->sk_state == TCP_LISTEN) {
2335+
tcp_set_state(ssk, TCP_CLOSE);
2336+
mptcp_subflow_queue_clean(ssk);
2337+
inet_csk_listen_stop(ssk);
2338+
}
23342339
__tcp_close(ssk, 0);
23352340

23362341
/* close acquired an extra ref */

net/mptcp/protocol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ struct mptcp_sock {
306306

307307
u32 setsockopt_seq;
308308
char ca_name[TCP_CA_NAME_MAX];
309+
struct mptcp_sock *dl_next;
309310
};
310311

311312
#define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock)
@@ -608,6 +609,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
608609
struct mptcp_subflow_context *subflow);
609610
void mptcp_subflow_send_ack(struct sock *ssk);
610611
void mptcp_subflow_reset(struct sock *ssk);
612+
void mptcp_subflow_queue_clean(struct sock *ssk);
611613
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
612614
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
613615

net/mptcp/subflow.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,58 @@ static void subflow_state_change(struct sock *sk)
17231723
}
17241724
}
17251725

1726+
void mptcp_subflow_queue_clean(struct sock *listener_ssk)
1727+
{
1728+
struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
1729+
struct mptcp_sock *msk, *next, *head = NULL;
1730+
struct request_sock *req;
1731+
1732+
/* build a list of all unaccepted mptcp sockets */
1733+
spin_lock_bh(&queue->rskq_lock);
1734+
for (req = queue->rskq_accept_head; req; req = req->dl_next) {
1735+
struct mptcp_subflow_context *subflow;
1736+
struct sock *ssk = req->sk;
1737+
struct mptcp_sock *msk;
1738+
1739+
if (!sk_is_mptcp(ssk))
1740+
continue;
1741+
1742+
subflow = mptcp_subflow_ctx(ssk);
1743+
if (!subflow || !subflow->conn)
1744+
continue;
1745+
1746+
/* skip if already in list */
1747+
msk = mptcp_sk(subflow->conn);
1748+
if (msk->dl_next || msk == head)
1749+
continue;
1750+
1751+
msk->dl_next = head;
1752+
head = msk;
1753+
}
1754+
spin_unlock_bh(&queue->rskq_lock);
1755+
if (!head)
1756+
return;
1757+
1758+
/* can't acquire the msk socket lock under the subflow one,
1759+
* or will cause ABBA deadlock
1760+
*/
1761+
release_sock(listener_ssk);
1762+
1763+
for (msk = head; msk; msk = next) {
1764+
struct sock *sk = (struct sock *)msk;
1765+
bool slow;
1766+
1767+
slow = lock_sock_fast_nested(sk);
1768+
next = msk->dl_next;
1769+
msk->first = NULL;
1770+
msk->dl_next = NULL;
1771+
unlock_sock_fast(sk, slow);
1772+
}
1773+
1774+
/* we are still under the listener msk socket lock */
1775+
lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
1776+
}
1777+
17261778
static int subflow_ulp_init(struct sock *sk)
17271779
{
17281780
struct inet_connection_sock *icsk = inet_csk(sk);

0 commit comments

Comments
 (0)