]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ksmbd: add buffer validation for smb direct
authorHyunchul Lee <hyc.lee@gmail.com>
Thu, 14 Oct 2021 21:02:50 +0000 (06:02 +0900)
committerSteve French <stfrench@microsoft.com>
Fri, 15 Oct 2021 14:18:29 +0000 (09:18 -0500)
Add buffer validation for smb direct.

Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/transport_rdma.c

index 3a7fa23ba8508c952eb498154adbb9ca8eaa0ee0..a2fd5a4d4cd5e4924dfb376ee16ebcb8bf4c4e04 100644 (file)
@@ -549,6 +549,10 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
 
        switch (recvmsg->type) {
        case SMB_DIRECT_MSG_NEGOTIATE_REQ:
+               if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) {
+                       put_empty_recvmsg(t, recvmsg);
+                       return;
+               }
                t->negotiation_requested = true;
                t->full_packet_received = true;
                wake_up_interruptible(&t->wait_status);
@@ -556,10 +560,23 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
        case SMB_DIRECT_MSG_DATA_TRANSFER: {
                struct smb_direct_data_transfer *data_transfer =
                        (struct smb_direct_data_transfer *)recvmsg->packet;
-               int data_length = le32_to_cpu(data_transfer->data_length);
+               unsigned int data_length;
                int avail_recvmsg_count, receive_credits;
 
+               if (wc->byte_len <
+                   offsetof(struct smb_direct_data_transfer, padding)) {
+                       put_empty_recvmsg(t, recvmsg);
+                       return;
+               }
+
+               data_length = le32_to_cpu(data_transfer->data_length);
                if (data_length) {
+                       if (wc->byte_len < sizeof(struct smb_direct_data_transfer) +
+                           (u64)data_length) {
+                               put_empty_recvmsg(t, recvmsg);
+                               return;
+                       }
+
                        if (t->full_packet_received)
                                recvmsg->first_segment = true;
 
@@ -568,7 +585,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                        else
                                t->full_packet_received = true;
 
-                       enqueue_reassembly(t, recvmsg, data_length);
+                       enqueue_reassembly(t, recvmsg, (int)data_length);
                        wake_up_interruptible(&t->wait_reassembly_queue);
 
                        spin_lock(&t->receive_credit_lock);