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
This commit is contained in:
parent
5cf57f1f53
commit
5e278a5264
@ -221,7 +221,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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user