]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: fix racy issue under cocurrent smb2 tree disconnect
authorNamjae Jeon <linkinjeon@kernel.org>
Mon, 18 Dec 2023 15:33:52 +0000 (00:33 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Dec 2023 09:41:55 +0000 (10:41 +0100)
[ Upstream commit 30210947a343b6b3ca13adc9bfc88e1543e16dd5 ]

There is UAF issue under cocurrent smb2 tree disconnect.
This patch introduce TREE_CONN_EXPIRE flags for tcon to avoid cocurrent
access.

Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20592
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ksmbd/mgmt/tree_connect.c
fs/ksmbd/mgmt/tree_connect.h
fs/ksmbd/smb2pdu.c

index aa9c138d5851099418caa23a9dcbc15fe0634df6..f07a05f376513ea987811f5aca092de8f5dd3ac5 100644 (file)
@@ -109,7 +109,15 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
 struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
                                                  unsigned int id)
 {
-       return xa_load(&sess->tree_conns, id);
+       struct ksmbd_tree_connect *tcon;
+
+       tcon = xa_load(&sess->tree_conns, id);
+       if (tcon) {
+               if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
+                       tcon = NULL;
+       }
+
+       return tcon;
 }
 
 struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
index 0f97ddc1e39c07919ed5bc153a41cb77ea716316..700df36cf3e30117d6528c80eda5425018c3e046 100644 (file)
@@ -14,6 +14,8 @@ struct ksmbd_share_config;
 struct ksmbd_user;
 struct ksmbd_conn;
 
+#define TREE_CONN_EXPIRE               1
+
 struct ksmbd_tree_connect {
        int                             id;
 
@@ -25,6 +27,7 @@ struct ksmbd_tree_connect {
 
        int                             maximal_access;
        bool                            posix_extensions;
+       unsigned long                   status;
 };
 
 struct ksmbd_tree_conn_status {
index ef68cb51048d932e62fd03b0f96a333346de07d8..7d16510e3392d620c6689b8ab90731cf2f1adfaf 100644 (file)
@@ -2083,11 +2083,12 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
 
        ksmbd_debug(SMB, "request\n");
 
-       if (!tcon) {
+       if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
                struct smb2_tree_disconnect_req *req =
                        smb2_get_msg(work->request_buf);
 
                ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+
                rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
                smb2_set_err_rsp(work);
                return 0;