ksmbd: keep compound responses on query info errors

Do not reset the RFC1002 length of the complete response when a query
info buffer is too small. The current command will add its error response
through ksmbd_iov_pin_rsp(), while resetting the base length can truncate
earlier responses in a compound request.

This lets ksmbd return the earlier responses and the query-info error
response together. Remove the now-unused rsp_org parameter from the pipe
query-info helpers.

Fixes: e2b76ab8b5 ("ksmbd: add support for read compound")
Reported-by: Mobin Aydinfar <mobin@mobintestserver.ir>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon 2026-09-09 09:58:48 +09:00
parent f4fafaf021
commit 9fa26285ae

View File

@ -6275,21 +6275,18 @@ int smb2_query_dir(struct ksmbd_work *work)
* @reqOutputBufferLength: max buffer length expected in command response
* @fixed_len: minimum fixed response length
* @rsp: query info response buffer contains output buffer length
* @rsp_org: base response buffer pointer in case of chained response
*
* Return: 0 on success, otherwise error
*/
static int buffer_check_err(int reqOutputBufferLength,
unsigned int fixed_len,
struct smb2_query_info_rsp *rsp,
void *rsp_org)
struct smb2_query_info_rsp *rsp)
{
unsigned int output_len = le32_to_cpu(rsp->OutputBufferLength);
if (reqOutputBufferLength < fixed_len) {
pr_err("Invalid Buffer Size Requested\n");
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
*(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
return -EINVAL;
}
@ -6300,8 +6297,7 @@ static int buffer_check_err(int reqOutputBufferLength,
return 0;
}
static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
void *rsp_org)
static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
{
struct smb2_file_standard_info *sinfo;
@ -6316,8 +6312,7 @@ static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
cpu_to_le32(sizeof(struct smb2_file_standard_info));
}
static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
void *rsp_org)
static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
{
struct smb2_file_internal_info *file_info;
@ -6331,8 +6326,7 @@ static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp,
void *rsp_org)
struct smb2_query_info_rsp *rsp)
{
u64 id;
int rc;
@ -6357,16 +6351,16 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
switch (req->FileInfoClass) {
case FILE_STANDARD_INFORMATION:
get_standard_info_pipe(rsp, rsp_org);
get_standard_info_pipe(rsp);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
le32_to_cpu(rsp->OutputBufferLength),
rsp, rsp_org);
rsp);
break;
case FILE_INTERNAL_INFORMATION:
get_internal_info_pipe(rsp, id, rsp_org);
get_internal_info_pipe(rsp, id);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
le32_to_cpu(rsp->OutputBufferLength),
rsp, rsp_org);
rsp);
break;
default:
ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
@ -7202,8 +7196,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_PIPE)) {
/* smb2 info file called for pipe */
rc = smb2_get_info_file_pipe(work->sess, req, rsp,
work->response_buf);
rc = smb2_get_info_file_pipe(work->sess, req, rsp);
goto iov_pin_out;
}
@ -7321,7 +7314,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
fixed_len,
rsp, work->response_buf);
rsp);
}
ksmbd_fd_put(work, fp);
@ -7592,7 +7585,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
}
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
fixed_len,
rsp, work->response_buf);
rsp);
path_put(&path);
if (!rc)
@ -7706,7 +7699,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
le32_to_cpu(rsp->OutputBufferLength),
rsp, work->response_buf);
rsp);
if (rc)
goto err_out;