]> exis.tech > repos - linux.git/blobdiff - fs/smb/server/smb2misc.c
Merge tag 'hwmon-for-v7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
[linux.git] / fs / smb / server / smb2misc.c
index a1ddca21c47bf9617733415ef1af579f13c4d17e..9f3629c86291bc375dd95e7e56f615646238b39d 100644 (file)
@@ -261,8 +261,12 @@ calc_size_exit:
 
 static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
 {
-       return le32_to_cpu(h->InputBufferLength) +
-               le32_to_cpu(h->OutputBufferLength);
+       return le32_to_cpu(h->InputBufferLength);
+}
+
+static inline int smb2_query_info_resp_len(struct smb2_query_info_req *h)
+{
+       return le32_to_cpu(h->OutputBufferLength);
 }
 
 static inline int smb2_set_info_req_len(struct smb2_set_info_req *h)
@@ -297,9 +301,10 @@ static inline int smb2_ioctl_resp_len(struct smb2_ioctl_req *h)
                le32_to_cpu(h->MaxOutputResponse);
 }
 
-static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
+static int smb2_validate_credit_charge(struct ksmbd_work *work,
                                       struct smb2_hdr *hdr)
 {
+       struct ksmbd_conn *conn = work->conn;
        unsigned int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len;
        unsigned short credit_charge = le16_to_cpu(hdr->CreditCharge);
        void *__hdr = hdr;
@@ -308,6 +313,7 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
        switch (hdr->Command) {
        case SMB2_QUERY_INFO:
                req_len = smb2_query_info_req_len(__hdr);
+               expect_resp_len = smb2_query_info_resp_len(__hdr);
                break;
        case SMB2_SET_INFO:
                req_len = smb2_set_info_req_len(__hdr);
@@ -356,8 +362,10 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
                ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n",
                            credit_charge, conn->outstanding_credits);
                ret = 1;
-       } else
+       } else {
                conn->outstanding_credits += credit_charge;
+               work->credit_charge = credit_charge;
+       }
 
        spin_unlock(&conn->credits_lock);
 
@@ -399,6 +407,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
                return 1;
        }
 
+       if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) {
+               ksmbd_debug(SMB, "Message is too small for StructureSize2\n");
+               return 1;
+       }
+
        if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
                if (!(command == SMB2_OPLOCK_BREAK_HE &&
                    (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 ||
@@ -460,7 +473,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
 
 validate_credit:
        if ((work->conn->vals->req_capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
-           smb2_validate_credit_charge(work->conn, hdr))
+           smb2_validate_credit_charge(work, hdr))
                return 1;
 
        return 0;