ksmbd: limit pdu length size according to connection status
authorNamjae Jeon <linkinjeon@kernel.org>
Tue, 24 Jan 2023 15:13:20 +0000 (00:13 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 1 Feb 2023 07:34:38 +0000 (08:34 +0100)
commit 62c487b53a7ff31e322cf2874d3796b8202c54a5 upstream.

Stream protocol length will never be larger than 16KB until session setup.
After session setup, the size of requests will not be larger than
16KB + SMB2 MAX WRITE size. This patch limits these invalidly oversized
requests and closes the connection immediately.

Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-18259
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

index fd0a288..56be077 100644 (file)
@@ -280,7 +280,7 @@ int ksmbd_conn_handler_loop(void *p)
 {
        struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
        struct ksmbd_transport *t = conn->transport;
-       unsigned int pdu_size;
+       unsigned int pdu_size, max_allowed_pdu_size;
        char hdr_buf[4] = {0,};
        int size;
 
@@ -305,13 +305,26 @@ int ksmbd_conn_handler_loop(void *p)
                pdu_size = get_rfc1002_len(hdr_buf);
                ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
 
+               if (conn->status == KSMBD_SESS_GOOD)
+                       max_allowed_pdu_size =
+                               SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
+               else
+                       max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
+
+               if (pdu_size > max_allowed_pdu_size) {
+                       pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
+                                       pdu_size, max_allowed_pdu_size,
+                                       conn->status);
+                       break;
+               }
+
                /*
                 * Check if pdu size is valid (min : smb header size,
                 * max : 0x00FFFFFF).
                 */
                if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
                    pdu_size > MAX_STREAM_PROT_LEN) {
-                       continue;
+                       break;
                }
 
                /* 4 for rfc1002 length field */
index 092fdd3..f4baa98 100644 (file)
@@ -24,8 +24,9 @@
 
 #define SMB21_DEFAULT_IOSIZE   (1024 * 1024)
 #define SMB3_DEFAULT_TRANS_SIZE        (1024 * 1024)
-#define SMB3_MIN_IOSIZE        (64 * 1024)
-#define SMB3_MAX_IOSIZE        (8 * 1024 * 1024)
+#define SMB3_MIN_IOSIZE                (64 * 1024)
+#define SMB3_MAX_IOSIZE                (8 * 1024 * 1024)
+#define SMB3_MAX_MSGSIZE       (4 * 4096)
 
 /*
  *     Definitions for SMB2 Protocol Data Units (network frames)