]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ksmbd: validate session id and tree id in compound request
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 23 Jul 2023 06:21:11 +0000 (15:21 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:42:21 +0000 (09:42 +0200)
[ Upstream commit 3df0411e132ee74a87aa13142dfd2b190275332e ]

`smb2_get_msg()` in smb2_get_ksmbd_tcon() and smb2_check_user_session()
will always return the first request smb2 header in a compound request.
if `SMB2_TREE_CONNECT_HE` is the first command in compound request, will
return 0, i.e. The tree id check is skipped.
This patch use ksmbd_req_buf_next() to get current command in compound.

Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21506
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/server/smb2pdu.c

index ee954c5ab9c2b7c06a8473eb5440065b86db62e4..74c245809772ede5a3f0860b6b722d76f2c8e097 100644 (file)
@@ -86,9 +86,9 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
  */
 int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        unsigned int cmd = le16_to_cpu(req_hdr->Command);
-       int tree_id;
+       unsigned int tree_id;
 
        if (cmd == SMB2_TREE_CONNECT_HE ||
            cmd ==  SMB2_CANCEL_HE ||
@@ -113,7 +113,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have tcon\n");
                        return -EINVAL;
                }
-               if (work->tcon->id != tree_id) {
+               if (tree_id != UINT_MAX && work->tcon->id != tree_id) {
                        pr_err("tree id(%u) is different with id(%u) in first operation\n",
                                        tree_id, work->tcon->id);
                        return -EINVAL;
@@ -565,9 +565,9 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
  */
 int smb2_check_user_session(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        struct ksmbd_conn *conn = work->conn;
-       unsigned int cmd = conn->ops->get_cmd_val(work);
+       unsigned int cmd = le16_to_cpu(req_hdr->Command);
        unsigned long long sess_id;
 
        /*
@@ -593,7 +593,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have sess\n");
                        return -EINVAL;
                }
-               if (work->sess->id != sess_id) {
+               if (sess_id != ULLONG_MAX && work->sess->id != sess_id) {
                        pr_err("session id(%llu) is different with the first operation(%lld)\n",
                                        sess_id, work->sess->id);
                        return -EINVAL;