mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
ksmbd: fix share_conf UAF in tree_conn disconnect
__ksmbd_tree_conn_disconnect() drops the share_conf reference before
checking tree_conn->refcount. When someone uses SMB3 multichannel and
binds two connections to one session, a SESSION_LOGOFF on connection A
calls ksmbd_conn_wait_idle(conn) which only drains connection A's
request counter, not connection B's. This means there's a race condition:
requests already dispatched on connection B hold tree_conn references via
work->tcon. The disconnect path frees share_conf while those requests
are still walking work->tcon->share_conf, causing a use-after-free.
This fix combines the share_conf put with the tree_conn free so it
only happens when the last reference is dropped.
Fixes: b39a1833cc ("ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency")
Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
committed by
Steve French
parent
f338e77383
commit
5258572aa5
@@ -102,8 +102,10 @@ out_error:
|
||||
|
||||
void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
|
||||
{
|
||||
if (atomic_dec_and_test(&tcon->refcount))
|
||||
if (atomic_dec_and_test(&tcon->refcount)) {
|
||||
ksmbd_share_config_put(tcon->share_conf);
|
||||
kfree(tcon);
|
||||
}
|
||||
}
|
||||
|
||||
static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
|
||||
@@ -113,10 +115,11 @@ static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
|
||||
|
||||
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
|
||||
ksmbd_release_tree_conn_id(sess, tree_conn->id);
|
||||
ksmbd_share_config_put(tree_conn->share_conf);
|
||||
ksmbd_counter_dec(KSMBD_COUNTER_TREE_CONNS);
|
||||
if (atomic_dec_and_test(&tree_conn->refcount))
|
||||
if (atomic_dec_and_test(&tree_conn->refcount)) {
|
||||
ksmbd_share_config_put(tree_conn->share_conf);
|
||||
kfree(tree_conn);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user