]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: validate smb request protocol id
authorNamjae Jeon <linkinjeon@kernel.org>
Mon, 18 Dec 2023 15:34:02 +0000 (00:34 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Dec 2023 09:41:56 +0000 (10:41 +0100)
[ Upstream commit 1c1bcf2d3ea061613119b534f57507c377df20f9 ]

This patch add the validation for smb request protocol id.
If it is not one of the four ids(SMB1_PROTO_NUMBER, SMB2_PROTO_NUMBER,
SMB2_TRANSFORM_PROTO_NUM, SMB2_COMPRESSION_TRANSFORM_ID), don't allow
processing the request. And this will fix the following KASAN warning
also.

[   13.905265] BUG: KASAN: slab-out-of-bounds in init_smb2_rsp_hdr+0x1b9/0x1f0
[   13.905900] Read of size 16 at addr ffff888005fd2f34 by task kworker/0:2/44
...
[   13.908553] Call Trace:
[   13.908793]  <TASK>
[   13.908995]  dump_stack_lvl+0x33/0x50
[   13.909369]  print_report+0xcc/0x620
[   13.910870]  kasan_report+0xae/0xe0
[   13.911519]  kasan_check_range+0x35/0x1b0
[   13.911796]  init_smb2_rsp_hdr+0x1b9/0x1f0
[   13.912492]  handle_ksmbd_work+0xe5/0x820

Cc: stable@vger.kernel.org
Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
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/connection.c
fs/ksmbd/smb2pdu.h
fs/ksmbd/smb_common.c

index c3c8b64a4adc85794b2f707b17046db6fa9a4a0c..99ea5f1b324dc6c94cebd29d50c416a0ea71ad82 100644 (file)
@@ -364,8 +364,6 @@ int ksmbd_conn_handler_loop(void *p)
                        break;
 
                memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
-               if (!ksmbd_smb_request(conn))
-                       break;
 
                /*
                 * We already read 4 bytes to find out PDU size, now
@@ -383,6 +381,9 @@ int ksmbd_conn_handler_loop(void *p)
                        continue;
                }
 
+               if (!ksmbd_smb_request(conn))
+                       break;
+
                if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
                    SMB2_PROTO_NUMBER) {
                        if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
index a774889e0aa546946e5aeb8f4290a49c8de0af65..e1d0849ee68fd0b04adb872ef1d918dbff2618f0 100644 (file)
 
 #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) /* 'B''M''S' */
 #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
+#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc)
 
 #define SMB21_DEFAULT_IOSIZE   (1024 * 1024)
 #define SMB3_DEFAULT_IOSIZE    (4 * 1024 * 1024)
index 1c69811610dc1c990c7a61ac63b934a9c3a95e4f..d937e2f45c829a6d06d9a9c76b20c3cfaece4672 100644 (file)
@@ -158,7 +158,19 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
  */
 bool ksmbd_smb_request(struct ksmbd_conn *conn)
 {
-       return conn->request_buf[0] == 0;
+       __le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
+
+       if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
+               pr_err_ratelimited("smb2 compression not support yet");
+               return false;
+       }
+
+       if (*proto != SMB1_PROTO_NUMBER &&
+           *proto != SMB2_PROTO_NUMBER &&
+           *proto != SMB2_TRANSFORM_PROTO_NUM)
+               return false;
+
+       return true;
 }
 
 static bool supported_protocol(int idx)