mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
net/smc: fix socket use-after-free during link group termination
__smc_lgr_terminate() drops conns_lock after finding a connection in
lgr->conns_all, but before taking a reference on its socket. The connection
is embedded in the socket, and its registration reference protects it only
while the connection remains in the tree.
A concurrent close can unregister the connection and drop that reference,
freeing the socket before the termination worker reaches sock_hold().
The race is reachable when close overlaps link group termination.
Local stress testing reproduced the use-after-free and KASAN reported:
BUG: KASAN: slab-use-after-free in __smc_lgr_terminate.part.0 [smc]
Write of size 4 by task kworker/3:3
Workqueue: events smc_lgr_terminate_work [smc]
__smc_lgr_terminate.part.0 [smc]
The socket was allocated by smc_create(), freed through
slab_free_after_rcu_debug(), and was followed by:
refcount_t: addition on 0; use-after-free.
__smc_lgr_terminate.part.0 [smc]
Take the socket reference while conns_lock still protects the tree entry.
The unregister path then cannot drop the last reference until termination
has finished using the socket.
Fixes: 69318b5215 ("net/smc: improve abnormal termination locking")
Cc: stable@vger.kernel.org
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
Link: https://patch.msgid.link/20260723105454.87016-1-xuanqiang.luo@linux.dev
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
aef96eead2
commit
f621d6ebee
+1
-1
@@ -1572,10 +1572,10 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
|
||||
read_lock_bh(&lgr->conns_lock);
|
||||
node = rb_first(&lgr->conns_all);
|
||||
while (node) {
|
||||
read_unlock_bh(&lgr->conns_lock);
|
||||
conn = rb_entry(node, struct smc_connection, alert_node);
|
||||
smc = container_of(conn, struct smc_sock, conn);
|
||||
sock_hold(&smc->sk); /* sock_put below */
|
||||
read_unlock_bh(&lgr->conns_lock);
|
||||
lock_sock(&smc->sk);
|
||||
smc_conn_kill(conn, soft);
|
||||
release_sock(&smc->sk);
|
||||
|
||||
Reference in New Issue
Block a user