Skip to content

Commit 0a3f4f1

Browse files
Paolo Abenikuba-moo
Paolo Abeni
authored andcommitted
mptcp: fix UaF in listener shutdown
As reported by Christoph after having refactored the passive socket initialization, the mptcp listener shutdown path is prone to an UaF issue. BUG: KASAN: use-after-free in _raw_spin_lock_bh+0x73/0xe0 Write of size 4 at addr ffff88810cb23098 by task syz-executor731/1266 CPU: 1 PID: 1266 Comm: syz-executor731 Not tainted 6.2.0-rc59af4eaa31c1f6c00c8f1e448ed99a45c66340dd5 #6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x6e/0x91 print_report+0x16a/0x46f kasan_report+0xad/0x130 kasan_check_range+0x14a/0x1a0 _raw_spin_lock_bh+0x73/0xe0 subflow_error_report+0x6d/0x110 sk_error_report+0x3b/0x190 tcp_disconnect+0x138c/0x1aa0 inet_child_forget+0x6f/0x2e0 inet_csk_listen_stop+0x209/0x1060 __mptcp_close_ssk+0x52d/0x610 mptcp_destroy_common+0x165/0x640 mptcp_destroy+0x13/0x80 __mptcp_destroy_sock+0xe7/0x270 __mptcp_close+0x70e/0x9b0 mptcp_close+0x2b/0x150 inet_release+0xe9/0x1f0 __sock_release+0xd2/0x280 sock_close+0x15/0x20 __fput+0x252/0xa20 task_work_run+0x169/0x250 exit_to_user_mode_prepare+0x113/0x120 syscall_exit_to_user_mode+0x1d/0x40 do_syscall_64+0x48/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc The msk grace period can legitly expire in between the last reference count dropped in mptcp_subflow_queue_clean() and the later eventual access in inet_csk_listen_stop() After the previous patch we don't need anymore special-casing msk listener socket cleanup: the mptcp worker will process each of the unaccepted msk sockets. Just drop the now unnecessary code. Please note this commit depends on the two parent ones: mptcp: refactor passive socket initialization mptcp: use the workqueue to destroy unaccepted sockets Fixes: 6aeed90 ("mptcp: fix race on unaccepted mptcp sockets") Cc: [email protected] Reported-and-tested-by: Christoph Paasch <[email protected]> Closes: multipath-tcp/mptcp_net-next#346 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]>
1 parent b6985b9 commit 0a3f4f1

File tree

3 files changed

+2
-78
lines changed

3 files changed

+2
-78
lines changed

net/mptcp/protocol.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,12 +2365,9 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
23652365
mptcp_subflow_drop_ctx(ssk);
23662366
} else {
23672367
/* otherwise tcp will dispose of the ssk and subflow ctx */
2368-
if (ssk->sk_state == TCP_LISTEN) {
2369-
tcp_set_state(ssk, TCP_CLOSE);
2370-
mptcp_subflow_queue_clean(sk, ssk);
2371-
inet_csk_listen_stop(ssk);
2368+
if (ssk->sk_state == TCP_LISTEN)
23722369
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
2373-
}
2370+
23742371
__tcp_close(ssk, 0);
23752372

23762373
/* close acquired an extra ref */

net/mptcp/protocol.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,6 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
629629
struct mptcp_subflow_context *subflow);
630630
void __mptcp_subflow_send_ack(struct sock *ssk);
631631
void mptcp_subflow_reset(struct sock *ssk);
632-
void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk);
633632
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
634633
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
635634
bool __mptcp_close(struct sock *sk, long timeout);

net/mptcp/subflow.c

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,78 +1826,6 @@ static void subflow_state_change(struct sock *sk)
18261826
}
18271827
}
18281828

1829-
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
1830-
{
1831-
struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
1832-
struct mptcp_sock *msk, *next, *head = NULL;
1833-
struct request_sock *req;
1834-
1835-
/* build a list of all unaccepted mptcp sockets */
1836-
spin_lock_bh(&queue->rskq_lock);
1837-
for (req = queue->rskq_accept_head; req; req = req->dl_next) {
1838-
struct mptcp_subflow_context *subflow;
1839-
struct sock *ssk = req->sk;
1840-
struct mptcp_sock *msk;
1841-
1842-
if (!sk_is_mptcp(ssk))
1843-
continue;
1844-
1845-
subflow = mptcp_subflow_ctx(ssk);
1846-
if (!subflow || !subflow->conn)
1847-
continue;
1848-
1849-
/* skip if already in list */
1850-
msk = mptcp_sk(subflow->conn);
1851-
if (msk->dl_next || msk == head)
1852-
continue;
1853-
1854-
msk->dl_next = head;
1855-
head = msk;
1856-
}
1857-
spin_unlock_bh(&queue->rskq_lock);
1858-
if (!head)
1859-
return;
1860-
1861-
/* can't acquire the msk socket lock under the subflow one,
1862-
* or will cause ABBA deadlock
1863-
*/
1864-
release_sock(listener_ssk);
1865-
1866-
for (msk = head; msk; msk = next) {
1867-
struct sock *sk = (struct sock *)msk;
1868-
bool do_cancel_work;
1869-
1870-
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
1871-
next = msk->dl_next;
1872-
msk->first = NULL;
1873-
msk->dl_next = NULL;
1874-
1875-
do_cancel_work = __mptcp_close(sk, 0);
1876-
release_sock(sk);
1877-
if (do_cancel_work) {
1878-
/* lockdep will report a false positive ABBA deadlock
1879-
* between cancel_work_sync and the listener socket.
1880-
* The involved locks belong to different sockets WRT
1881-
* the existing AB chain.
1882-
* Using a per socket key is problematic as key
1883-
* deregistration requires process context and must be
1884-
* performed at socket disposal time, in atomic
1885-
* context.
1886-
* Just tell lockdep to consider the listener socket
1887-
* released here.
1888-
*/
1889-
mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_);
1890-
mptcp_cancel_work(sk);
1891-
mutex_acquire(&listener_sk->sk_lock.dep_map,
1892-
SINGLE_DEPTH_NESTING, 0, _RET_IP_);
1893-
}
1894-
sock_put(sk);
1895-
}
1896-
1897-
/* we are still under the listener msk socket lock */
1898-
lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
1899-
}
1900-
19011829
static int subflow_ulp_init(struct sock *sk)
19021830
{
19031831
struct inet_connection_sock *icsk = inet_csk(sk);

0 commit comments

Comments
 (0)