From 284dc80ff529a0b454f11b6c2fea0d5daf6f315f Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 26 Jun 2026 10:51:16 +0900 Subject: [PATCH] ksmbd: fix credit charge calculation for SMB2 QUERY_INFO smb2_validate_credit_charge() computes the credit charge a request is allowed to consume from the payload size: CreditCharge = (max(SendPayloadSize, ResponsePayloadSize) - 1)/65536 + 1 For SMB2 QUERY_INFO, the server must validate CreditCharge based on the *maximum* of InputBufferLength and OutputBufferLength. ksmbd instead summed the two lengths, which overestimates the required charge. As a result a single-credit QUERY_INFO whose InputBufferLength and OutputBufferLength each fit in 64KB but whose sum exceeds 64KB is rejected with STATUS_INVALID_PARAMETER, even though it is a valid request. IOCTL already uses max() of the request and response sizes; make QUERY_INFO consistent by feeding InputBufferLength as the request length and OutputBufferLength as the expected response length so that smb2_validate_credit_charge() takes their maximum. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smb2misc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c index a1ddca21c47b..35fba49d27d6 100644 --- a/fs/smb/server/smb2misc.c +++ b/fs/smb/server/smb2misc.c @@ -261,8 +261,12 @@ static int smb2_calc_size(void *buf, unsigned int *len) 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) @@ -308,6 +312,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);