mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
then acquires lock_sock_nested() only after the check passes. This
opens a window where smc_close_active() can transition the listener
to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
queue, and release the lock, all between the lockless read and the
delayed lock acquisition:
smc_listen_work (smc_hs_wq) smc_close_active()
------------------------------- -------------------------
release_sock(child)
if (sk_state == SMC_LISTEN) TRUE
lock_sock(listener)
sk_state = SMC_CLOSED
smc_close_cleanup_listen()
release_sock(listener)
flush_work(tcp_listen_work)
lock_sock_nested(listener)
smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
smc_close_active() flushes only tcp_listen_work. Work items already
dispatched onto smc_hs_wq for the CLC handshake continue running
unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
is never released, so the child smc_sock, its clcsock, and the
reference all leak. A remote peer that opens TCP connections while the
server calls close() can exhaust kernel memory.
Move lock_sock_nested() to before the sk_state check so that the test
and the enqueue are atomic under the listener lock.
Fixes:
|
||
|---|---|---|
| .. | ||
| af_smc.c | ||
| Kconfig | ||
| Makefile | ||
| smc_cdc.c | ||
| smc_cdc.h | ||
| smc_clc.c | ||
| smc_clc.h | ||
| smc_close.c | ||
| smc_close.h | ||
| smc_core.c | ||
| smc_core.h | ||
| smc_diag.c | ||
| smc_hs_bpf.c | ||
| smc_hs_bpf.h | ||
| smc_ib.c | ||
| smc_ib.h | ||
| smc_inet.c | ||
| smc_inet.h | ||
| smc_ism.c | ||
| smc_ism.h | ||
| smc_llc.c | ||
| smc_llc.h | ||
| smc_netlink.c | ||
| smc_netlink.h | ||
| smc_netns.h | ||
| smc_pnet.c | ||
| smc_pnet.h | ||
| smc_rx.c | ||
| smc_rx.h | ||
| smc_stats.c | ||
| smc_stats.h | ||
| smc_sysctl.c | ||
| smc_sysctl.h | ||
| smc_tracepoint.c | ||
| smc_tracepoint.h | ||
| smc_tx.c | ||
| smc_tx.h | ||
| smc_wr.c | ||
| smc_wr.h | ||
| smc.h | ||