Skip to content

Commit 9ef683b

Browse files
committed
mptcp: fix race on unaccepted mptcp sockets
jira VULN-52916 cve CVE-2022-49669 commit-author Paolo Abeni <[email protected]> commit 6aeed90 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]> (cherry picked from commit 6aeed90) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent 98830ec commit 9ef683b

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
@@ -2263,6 +2263,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
22632263
kfree_rcu(subflow, rcu);
22642264
} else {
22652265
/* otherwise tcp will dispose of the ssk and subflow ctx */
2266+
if (ssk->sk_state == TCP_LISTEN) {
2267+
tcp_set_state(ssk, TCP_CLOSE);
2268+
mptcp_subflow_queue_clean(ssk);
2269+
inet_csk_listen_stop(ssk);
2270+
}
22662271
__tcp_close(ssk, 0);
22672272

22682273
/* close acquired an extra ref */

net/mptcp/protocol.h

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

262262
u32 setsockopt_seq;
263263
char ca_name[TCP_CA_NAME_MAX];
264+
struct mptcp_sock *dl_next;
264265
};
265266

266267
#define mptcp_lock_sock(___sk, cb) do { \
@@ -549,6 +550,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
549550
struct mptcp_subflow_context *subflow);
550551
void mptcp_subflow_send_ack(struct sock *ssk);
551552
void mptcp_subflow_reset(struct sock *ssk);
553+
void mptcp_subflow_queue_clean(struct sock *ssk);
552554
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
553555
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
554556

net/mptcp/subflow.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,58 @@ static void subflow_state_change(struct sock *sk)
15141514
}
15151515
}
15161516

1517+
void mptcp_subflow_queue_clean(struct sock *listener_ssk)
1518+
{
1519+
struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
1520+
struct mptcp_sock *msk, *next, *head = NULL;
1521+
struct request_sock *req;
1522+
1523+
/* build a list of all unaccepted mptcp sockets */
1524+
spin_lock_bh(&queue->rskq_lock);
1525+
for (req = queue->rskq_accept_head; req; req = req->dl_next) {
1526+
struct mptcp_subflow_context *subflow;
1527+
struct sock *ssk = req->sk;
1528+
struct mptcp_sock *msk;
1529+
1530+
if (!sk_is_mptcp(ssk))
1531+
continue;
1532+
1533+
subflow = mptcp_subflow_ctx(ssk);
1534+
if (!subflow || !subflow->conn)
1535+
continue;
1536+
1537+
/* skip if already in list */
1538+
msk = mptcp_sk(subflow->conn);
1539+
if (msk->dl_next || msk == head)
1540+
continue;
1541+
1542+
msk->dl_next = head;
1543+
head = msk;
1544+
}
1545+
spin_unlock_bh(&queue->rskq_lock);
1546+
if (!head)
1547+
return;
1548+
1549+
/* can't acquire the msk socket lock under the subflow one,
1550+
* or will cause ABBA deadlock
1551+
*/
1552+
release_sock(listener_ssk);
1553+
1554+
for (msk = head; msk; msk = next) {
1555+
struct sock *sk = (struct sock *)msk;
1556+
bool slow;
1557+
1558+
slow = lock_sock_fast_nested(sk);
1559+
next = msk->dl_next;
1560+
msk->first = NULL;
1561+
msk->dl_next = NULL;
1562+
unlock_sock_fast(sk, slow);
1563+
}
1564+
1565+
/* we are still under the listener msk socket lock */
1566+
lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
1567+
}
1568+
15171569
static int subflow_ulp_init(struct sock *sk)
15181570
{
15191571
struct inet_connection_sock *icsk = inet_csk(sk);

0 commit comments

Comments
 (0)