1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

smb2_ioctl: fix truncated FSCTL_QUERY_ALLOCATED_RANGES responses

As per MS-FSA 2.1.5.10.22 FSCTL_QUERY_ALLOCATED_RANGES, if response
range entries exceed in_max_output, then we should respond with
STATUS_BUFFER_OVERFLOW and a truncated output buffer.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=15699

Reported-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Noel Power <npower@samba.org>

Autobuild-User(master): David Disseldorp <ddiss@samba.org>
Autobuild-Date(master): Wed Aug 28 08:54:11 UTC 2024 on atb-devel-224

(cherry picked from commit 5e278a5264)

Autobuild-User(v4-20-test): Jule Anger <janger@samba.org>
Autobuild-Date(v4-20-test): Fri Aug 30 09:01:54 UTC 2024 on atb-devel-224
This commit is contained in:
David Disseldorp 2024-08-23 12:55:58 +00:00 committed by Jule Anger
parent f22c56b06e
commit 72aa92c67d
4 changed files with 38 additions and 24 deletions

View File

@ -222,7 +222,6 @@
^samba3.smb2.lease.statopen3
^samba3.smb2.lease.unlink # we currently do not downgrade RH lease to R after unlink
^samba4.smb2.ioctl.compress_notsup.*\(ad_dc_ntvfs\)
^samba4.smb2.ioctl.sparse_qar_truncated # bug 15699
^samba3.raw.session.*reauth2 # maybe fix this?
^samba3.rpc.lsa.secrets.seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY
^samba3.rpc.samr.passwords.badpwdcount.samr.badPwdCount\(nt4_dc\) # We fail this test currently

View File

@ -268,7 +268,8 @@ static bool smbd_smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)
&& ((ctl_code == FSCTL_PIPE_TRANSCEIVE)
|| (ctl_code == FSCTL_PIPE_PEEK)
|| (ctl_code == FSCTL_DFS_GET_REFERRALS))) {
|| (ctl_code == FSCTL_DFS_GET_REFERRALS)
|| (ctl_code == FSCTL_QUERY_ALLOCATED_RANGES))) {
return false;
}
@ -344,6 +345,7 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq)
* in:
* - fsctl_dfs_get_refers()
* - smbd_smb2_ioctl_pipe_read_done()
* - fsctl_qar()
*/
status = NT_STATUS_BUFFER_TOO_SMALL;
}

View File

@ -3,7 +3,7 @@
Core SMB2 server
Copyright (C) Stefan Metzmacher 2009
Copyright (C) David Disseldorp 2013-2015
Copyright (C) David Disseldorp 2013-2024
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -538,6 +538,7 @@ static NTSTATUS fsctl_qar_seek_fill(TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
off_t curr_off,
off_t max_off,
size_t in_max_output,
DATA_BLOB *qar_array_blob)
{
NTSTATUS status = NT_STATUS_NOT_SUPPORTED;
@ -578,6 +579,17 @@ static NTSTATUS fsctl_qar_seek_fill(TALLOC_CTX *mem_ctx,
return NT_STATUS_INTERNAL_ERROR;
}
if (qar_array_blob->length + sizeof(qar_buf) > in_max_output) {
/*
* Earlier check ensures space for one range or more.
* Subsequent overflow results in a truncated response.
*/
DBG_NOTICE("truncated QAR output: need > %zu, max %zu\n",
qar_array_blob->length + sizeof(qar_buf),
in_max_output);
return STATUS_BUFFER_OVERFLOW;
}
qar_buf.file_off = data_off;
/* + 1 to convert maximum offset to length */
qar_buf.len = MIN(hole_off, max_off + 1) - data_off;
@ -652,6 +664,13 @@ static NTSTATUS fsctl_qar(TALLOC_CTX *mem_ctx,
return NT_STATUS_INVALID_PARAMETER;
}
/* must have enough space for at least one range */
if (in_max_output < sizeof(struct file_alloced_range_buf)) {
DEBUG(2, ("QAR max %lu insufficient for one range\n",
(unsigned long)in_max_output));
return NT_STATUS_BUFFER_TOO_SMALL;
}
/*
* Maximum offset is either the last valid offset _before_ EOF, or the
* last byte offset within the requested range. -1 converts length to
@ -687,31 +706,24 @@ static NTSTATUS fsctl_qar(TALLOC_CTX *mem_ctx,
status = fsctl_qar_buf_push(mem_ctx, &qar_buf, &qar_array_blob);
} else {
status = fsctl_qar_seek_fill(mem_ctx, fsp, qar_req.buf.file_off,
max_off, &qar_array_blob);
}
if (!NT_STATUS_IS_OK(status)) {
return status;
max_off, in_max_output,
&qar_array_blob);
}
/* marshall response buffer. */
qar_rsp.far_buf_array = qar_array_blob;
if (NT_STATUS_IS_OK(status)
|| NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
/* marshall response. STATUS_BUFFER_OVERFLOW=truncated */
qar_rsp.far_buf_array = qar_array_blob;
ndr_ret = ndr_push_struct_blob(out_output, mem_ctx, &qar_rsp,
(ndr_push_flags_fn_t)ndr_push_fsctl_query_alloced_ranges_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
DEBUG(0, ("failed to marshall QAR rsp\n"));
return NT_STATUS_INVALID_PARAMETER;
ndr_ret = ndr_push_struct_blob(out_output, mem_ctx, &qar_rsp,
(ndr_push_flags_fn_t)ndr_push_fsctl_query_alloced_ranges_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
DEBUG(0, ("failed to marshall QAR rsp\n"));
return NT_STATUS_INVALID_PARAMETER;
}
}
if (out_output->length > in_max_output) {
DEBUG(2, ("QAR output len %lu exceeds max %lu\n",
(unsigned long)out_output->length,
(unsigned long)in_max_output));
data_blob_free(out_output);
return NT_STATUS_BUFFER_TOO_SMALL;
}
return NT_STATUS_OK;
return status;
}
static void smb2_ioctl_filesys_dup_extents_done(struct tevent_req *subreq);

View File

@ -86,7 +86,8 @@ static bool smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)
&& ((ctl_code == FSCTL_PIPE_TRANSCEIVE)
|| (ctl_code == FSCTL_PIPE_PEEK)
|| (ctl_code == FSCTL_DFS_GET_REFERRALS))) {
|| (ctl_code == FSCTL_DFS_GET_REFERRALS)
|| (ctl_code == FSCTL_QUERY_ALLOCATED_RANGES))) {
return false;
}