mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
s3/vfs: make SMB_VFS_OFFLOAD_WRITE_SEND offload token based
Remove the source fsp argument and instead pass the offload token generated with SMB_VFS_OFFLOAD_READ_SEND/RECV. An actual offload fsctl is not implemented yet, neither in the VFS nor at the SMB ioctl layer, and returns NT_STATUS_NOT_IMPLEMENTED With these changes we now pass the copy-chunk-across-shares test. Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
parent
d50f307e97
commit
3645f83a3c
@ -585,8 +585,9 @@ struct skel_cc_state {
|
||||
static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
|
@ -719,8 +719,9 @@ static void skel_offload_write_done(struct tevent_req *subreq);
|
||||
static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
@ -737,7 +738,7 @@ static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *hand
|
||||
|
||||
state->handle = handle;
|
||||
subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev,
|
||||
src_fsp, src_off,
|
||||
fsctl, token, transfer_offset,
|
||||
dest_fsp, dest_off, num, flags);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
|
@ -1,2 +0,0 @@
|
||||
^samba3.smb2.ioctl.copy_chunk_across_shares
|
||||
^samba3.smb2.ioctl fs_specific.copy_chunk_across_shares
|
@ -799,8 +799,9 @@ struct vfs_fn_pointers {
|
||||
struct tevent_req *(*offload_write_send_fn)(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t to_copy,
|
||||
@ -1379,8 +1380,9 @@ NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
|
||||
struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
|
@ -425,10 +425,10 @@
|
||||
#define SMB_VFS_NEXT_OFFLOAD_READ_RECV(req, handle, mem_ctx, token_blob) \
|
||||
smb_vfs_call_offload_read_recv((req), (handle)->next, (mem_ctx), (token_blob))
|
||||
|
||||
#define SMB_VFS_OFFLOAD_WRITE_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \
|
||||
smb_vfs_call_offload_write_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags))
|
||||
#define SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \
|
||||
smb_vfs_call_offload_write_send((handle)->next, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags))
|
||||
#define SMB_VFS_OFFLOAD_WRITE_SEND(conn, mem_ctx, ev, fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags) \
|
||||
smb_vfs_call_offload_write_send((conn)->vfs_handles, (mem_ctx), (ev), (fsctl), (token), (transfer_offset), (dest_fsp), (dest_off), (num), (flags))
|
||||
#define SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags) \
|
||||
smb_vfs_call_offload_write_send((handle)->next, (mem_ctx), (ev), (fsctl), (token), (transfer_offset), (dest_fsp), (dest_off), (num), (flags))
|
||||
|
||||
#define SMB_VFS_OFFLOAD_WRITE_RECV(conn, req, copied) \
|
||||
smb_vfs_call_offload_write_recv((conn)->vfs_handles, (req), (copied))
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "includes.h"
|
||||
#include "smbd/smbd.h"
|
||||
#include "smbd/globals.h"
|
||||
#include "../libcli/security/security.h"
|
||||
#include "dbwrap/dbwrap.h"
|
||||
#include "dbwrap/dbwrap_rbt.h"
|
||||
#include "dbwrap/dbwrap_open.h"
|
||||
@ -220,3 +221,92 @@ NTSTATUS vfs_offload_token_create_blob(TALLOC_CTX *mem_ctx,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl,
|
||||
files_struct *src_fsp,
|
||||
files_struct *dst_fsp)
|
||||
{
|
||||
if (src_fsp->vuid != dst_fsp->vuid) {
|
||||
DBG_INFO("copy chunk handles not in the same session.\n");
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(src_fsp->op->status)) {
|
||||
DBG_INFO("copy chunk source handle invalid: %s\n",
|
||||
nt_errstr(src_fsp->op->status));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(dst_fsp->op->status)) {
|
||||
DBG_INFO("copy chunk destination handle invalid: %s\n",
|
||||
nt_errstr(dst_fsp->op->status));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (src_fsp->deferred_close != NULL) {
|
||||
DBG_INFO("copy chunk src handle with deferred close.\n");
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (dst_fsp->deferred_close != NULL) {
|
||||
DBG_INFO("copy chunk dst handle with deferred close.\n");
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (src_fsp->is_directory) {
|
||||
DBG_INFO("copy chunk no read on src directory handle (%s).\n",
|
||||
smb_fname_str_dbg(src_fsp->fsp_name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (dst_fsp->is_directory) {
|
||||
DBG_INFO("copy chunk no read on dst directory handle (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (IS_IPC(src_fsp->conn) || IS_IPC(dst_fsp->conn)) {
|
||||
DBG_INFO("copy chunk no access on IPC$ handle.\n");
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (IS_PRINT(src_fsp->conn) || IS_PRINT(dst_fsp->conn)) {
|
||||
DBG_INFO("copy chunk no access on PRINT handle.\n");
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/*
|
||||
* [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
|
||||
* The server MUST fail the request with STATUS_ACCESS_DENIED if any of
|
||||
* the following are true:
|
||||
* - The Open.GrantedAccess of the destination file does not include
|
||||
* FILE_WRITE_DATA or FILE_APPEND_DATA.
|
||||
*
|
||||
* A non writable dst handle also doesn't make sense for other fsctls.
|
||||
*/
|
||||
if (!CHECK_WRITE(dst_fsp)) {
|
||||
DBG_INFO("dest handle not writable (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
/*
|
||||
* - The Open.GrantedAccess of the destination file does not include
|
||||
* FILE_READ_DATA, and the CtlCode is FSCTL_SRV_COPYCHUNK.
|
||||
*/
|
||||
if ((fsctl == FSCTL_SRV_COPYCHUNK) && !CHECK_READ_IOCTL(dst_fsp)) {
|
||||
DBG_INFO("copy chunk no read on dest handle (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
/*
|
||||
* - The Open.GrantedAccess of the source file does not include
|
||||
* FILE_READ_DATA access.
|
||||
*/
|
||||
if (!CHECK_READ_SMB2(src_fsp)) {
|
||||
DBG_INFO("src handle not readable (%s).\n",
|
||||
smb_fname_str_dbg(src_fsp->fsp_name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -34,4 +34,7 @@ NTSTATUS vfs_offload_token_create_blob(TALLOC_CTX *mem_ctx,
|
||||
const files_struct *fsp,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token_blob);
|
||||
NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl,
|
||||
files_struct *src_fsp,
|
||||
files_struct *dst_fsp);
|
||||
#endif
|
||||
|
@ -206,8 +206,9 @@ static void btrfs_offload_write_done(struct tevent_req *subreq);
|
||||
static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
@ -218,7 +219,10 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
|
||||
struct btrfs_ioctl_clone_range_args cr_args;
|
||||
struct lock_struct src_lck;
|
||||
struct lock_struct dest_lck;
|
||||
off_t src_off = transfer_offset;
|
||||
files_struct *src_fsp = NULL;
|
||||
int ret;
|
||||
bool handle_offload_write = true;
|
||||
NTSTATUS status;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &cc_state, struct btrfs_cc_state);
|
||||
@ -233,16 +237,38 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
|
||||
|
||||
cc_state->handle = handle;
|
||||
|
||||
status = vfs_offload_token_db_fetch_fsp(btrfs_offload_ctx,
|
||||
token, &src_fsp);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
switch (fsctl) {
|
||||
case FSCTL_SRV_COPYCHUNK:
|
||||
case FSCTL_SRV_COPYCHUNK_WRITE:
|
||||
case FSCTL_DUP_EXTENTS_TO_FILE:
|
||||
break;
|
||||
|
||||
default:
|
||||
handle_offload_write = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (num == 0) {
|
||||
/*
|
||||
* With a @src_length of zero, BTRFS_IOC_CLONE_RANGE clones
|
||||
* all data from @src_offset->EOF! This is certainly not what
|
||||
* the caller expects, and not what vfs_default does.
|
||||
*/
|
||||
handle_offload_write = false;
|
||||
}
|
||||
|
||||
if (!handle_offload_write) {
|
||||
cc_state->subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
|
||||
cc_state, ev,
|
||||
src_fsp,
|
||||
src_off,
|
||||
fsctl,
|
||||
token,
|
||||
transfer_offset,
|
||||
dest_fsp,
|
||||
dest_off,
|
||||
num, flags);
|
||||
@ -255,6 +281,13 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
|
||||
return req;
|
||||
}
|
||||
|
||||
status = vfs_offload_token_check_handles(
|
||||
fsctl, src_fsp, dest_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
status = vfs_stat_fsp(src_fsp);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return tevent_req_post(req, ev);
|
||||
@ -323,8 +356,9 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
|
||||
(unsigned long long)cr_args.dest_offset));
|
||||
cc_state->subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
|
||||
cc_state, ev,
|
||||
src_fsp,
|
||||
src_off,
|
||||
fsctl,
|
||||
token,
|
||||
transfer_offset,
|
||||
dest_fsp,
|
||||
dest_off,
|
||||
num, flags);
|
||||
|
@ -1689,6 +1689,7 @@ struct vfswrap_offload_write_state {
|
||||
struct lock_struct read_lck;
|
||||
bool write_lck_locked;
|
||||
struct lock_struct write_lck;
|
||||
DATA_BLOB *token;
|
||||
struct files_struct *src_fsp;
|
||||
off_t src_off;
|
||||
struct files_struct *dst_fsp;
|
||||
@ -1705,8 +1706,9 @@ static struct tevent_req *vfswrap_offload_write_send(
|
||||
struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t to_copy,
|
||||
@ -1715,10 +1717,9 @@ static struct tevent_req *vfswrap_offload_write_send(
|
||||
struct tevent_req *req;
|
||||
struct vfswrap_offload_write_state *state = NULL;
|
||||
size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
|
||||
files_struct *src_fsp = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct vfswrap_offload_write_state);
|
||||
if (req == NULL) {
|
||||
@ -1738,8 +1739,8 @@ static struct tevent_req *vfswrap_offload_write_send(
|
||||
|
||||
*state = (struct vfswrap_offload_write_state) {
|
||||
.ev = ev,
|
||||
.src_fsp = src_fsp,
|
||||
.src_off = src_off,
|
||||
.token = token,
|
||||
.src_off = transfer_offset,
|
||||
.dst_fsp = dest_fsp,
|
||||
.dst_off = dest_off,
|
||||
.to_copy = to_copy,
|
||||
@ -1747,11 +1748,44 @@ static struct tevent_req *vfswrap_offload_write_send(
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
switch (fsctl) {
|
||||
case FSCTL_SRV_COPYCHUNK:
|
||||
case FSCTL_SRV_COPYCHUNK_WRITE:
|
||||
break;
|
||||
|
||||
case FSCTL_OFFLOAD_WRITE:
|
||||
tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
|
||||
return tevent_req_post(req, ev);
|
||||
|
||||
default:
|
||||
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* From here on we assume a copy-chunk fsctl
|
||||
*/
|
||||
|
||||
if (to_copy == 0) {
|
||||
tevent_req_done(req);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
|
||||
token, &src_fsp);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->src_fsp = src_fsp;
|
||||
|
||||
DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
|
||||
|
||||
status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->buf = talloc_array(state, uint8_t, num);
|
||||
if (tevent_req_nomem(state->buf, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
@ -1762,7 +1796,7 @@ static struct tevent_req *vfswrap_offload_write_send(
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
|
||||
if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
|
||||
/*
|
||||
* [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
|
||||
* If the SourceOffset or SourceOffset + Length extends beyond
|
||||
|
@ -5485,8 +5485,9 @@ static void fruit_offload_write_done(struct tevent_req *subreq);
|
||||
static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
@ -5496,6 +5497,8 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han
|
||||
struct fruit_offload_write_state *state;
|
||||
NTSTATUS status;
|
||||
struct fruit_config_data *config;
|
||||
off_t src_off = transfer_offset;
|
||||
files_struct *src_fsp = NULL;
|
||||
off_t to_copy = num;
|
||||
|
||||
DEBUG(10,("soff: %ju, doff: %ju, len: %ju\n",
|
||||
@ -5511,9 +5514,22 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han
|
||||
return NULL;
|
||||
}
|
||||
state->handle = handle;
|
||||
state->src_fsp = src_fsp;
|
||||
state->dst_fsp = dest_fsp;
|
||||
|
||||
switch (fsctl) {
|
||||
case FSCTL_SRV_COPYCHUNK:
|
||||
case FSCTL_SRV_COPYCHUNK_WRITE:
|
||||
status = vfs_offload_token_db_fetch_fsp(fruit_offload_ctx,
|
||||
token, &src_fsp);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->src_fsp = src_fsp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this a OS X copyfile style copychunk request with
|
||||
* a requested chunk count of 0 that was translated to a
|
||||
@ -5521,7 +5537,7 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han
|
||||
* = dest_off = num = 0.
|
||||
*/
|
||||
if ((src_off == 0) && (dest_off == 0) && (num == 0) &&
|
||||
src_fsp->aapl_copyfile_supported &&
|
||||
src_fsp != NULL && src_fsp->aapl_copyfile_supported &&
|
||||
dest_fsp->aapl_copyfile_supported)
|
||||
{
|
||||
status = vfs_stat_fsp(src_fsp);
|
||||
@ -5536,8 +5552,9 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han
|
||||
subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
|
||||
mem_ctx,
|
||||
ev,
|
||||
src_fsp,
|
||||
src_off,
|
||||
fsctl,
|
||||
token,
|
||||
transfer_offset,
|
||||
dest_fsp,
|
||||
dest_off,
|
||||
to_copy,
|
||||
|
@ -1944,8 +1944,9 @@ static NTSTATUS smb_full_audit_offload_read_recv(
|
||||
static struct tevent_req *smb_full_audit_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
@ -1953,8 +1954,9 @@ static struct tevent_req *smb_full_audit_offload_write_send(struct vfs_handle_st
|
||||
{
|
||||
struct tevent_req *req;
|
||||
|
||||
req = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, src_fsp,
|
||||
src_off, dest_fsp, dest_off, num,
|
||||
req = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev,
|
||||
fsctl, token, transfer_offset,
|
||||
dest_fsp, dest_off, num,
|
||||
flags);
|
||||
|
||||
do_log(SMB_VFS_OP_OFFLOAD_WRITE_SEND, req, handle, "");
|
||||
|
@ -2005,8 +2005,9 @@ static void smb_time_audit_offload_write_done(struct tevent_req *subreq);
|
||||
static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
@ -2025,7 +2026,7 @@ static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_st
|
||||
state->handle = handle;
|
||||
clock_gettime_mono(&state->ts_send);
|
||||
subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev,
|
||||
src_fsp, src_off,
|
||||
fsctl, token, transfer_offset,
|
||||
dest_fsp, dest_off, num, flags);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
|
@ -161,7 +161,6 @@ static NTSTATUS fsctl_dup_extents_check_sparse(struct files_struct *src_fsp,
|
||||
struct fsctl_dup_extents_state {
|
||||
struct tevent_context *ev;
|
||||
struct connection_struct *conn;
|
||||
struct files_struct *src_fsp;
|
||||
struct files_struct *dst_fsp;
|
||||
struct fsctl_dup_extents_to_file dup_extents;
|
||||
};
|
||||
@ -234,7 +233,6 @@ static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx,
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->src_fsp = src_fsp;
|
||||
|
||||
status = fsctl_dup_extents_check_lengths(src_fsp, dst_fsp,
|
||||
&state->dup_extents);
|
||||
@ -279,11 +277,11 @@ static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq)
|
||||
subreq, struct tevent_req);
|
||||
struct fsctl_dup_extents_state *state = tevent_req_data(
|
||||
req, struct fsctl_dup_extents_state);
|
||||
DATA_BLOB token_blob;
|
||||
DATA_BLOB token;
|
||||
NTSTATUS status;
|
||||
|
||||
status = SMB_VFS_OFFLOAD_READ_RECV(subreq, state->dst_fsp->conn,
|
||||
state, &token_blob);
|
||||
state, &token);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
@ -292,7 +290,8 @@ static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq)
|
||||
subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn,
|
||||
state,
|
||||
state->ev,
|
||||
state->src_fsp,
|
||||
FSCTL_DUP_EXTENTS_TO_FILE,
|
||||
&token,
|
||||
state->dup_extents.source_off,
|
||||
state->dst_fsp,
|
||||
state->dup_extents.target_off,
|
||||
|
@ -82,6 +82,8 @@ struct fsctl_srv_copychunk_state {
|
||||
uint32_t current_chunk;
|
||||
NTSTATUS status;
|
||||
off_t total_written;
|
||||
uint32_t ctl_code;
|
||||
DATA_BLOB token;
|
||||
struct files_struct *src_fsp;
|
||||
struct files_struct *dst_fsp;
|
||||
enum {
|
||||
@ -93,67 +95,6 @@ struct fsctl_srv_copychunk_state {
|
||||
};
|
||||
static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq);
|
||||
|
||||
static NTSTATUS copychunk_check_handles(uint32_t ctl_code,
|
||||
struct files_struct *src_fsp,
|
||||
struct files_struct *dst_fsp)
|
||||
{
|
||||
/*
|
||||
* [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
|
||||
* The server MUST fail the request with STATUS_ACCESS_DENIED if any of
|
||||
* the following are true:
|
||||
* - The Open.GrantedAccess of the destination file does not include
|
||||
* FILE_WRITE_DATA or FILE_APPEND_DATA.
|
||||
*/
|
||||
if (!CHECK_WRITE(dst_fsp)) {
|
||||
DEBUG(5, ("copy chunk no write on dest handle (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name) ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
/*
|
||||
* - The Open.GrantedAccess of the destination file does not include
|
||||
* FILE_READ_DATA, and the CtlCode is FSCTL_SRV_COPYCHUNK.
|
||||
*/
|
||||
if ((ctl_code == FSCTL_SRV_COPYCHUNK) &&
|
||||
!CHECK_READ_IOCTL(dst_fsp)) {
|
||||
DEBUG(5, ("copy chunk no read on dest handle (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name) ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
/*
|
||||
* - The Open.GrantedAccess of the source file does not include
|
||||
* FILE_READ_DATA access.
|
||||
*/
|
||||
if (!CHECK_READ_SMB2(src_fsp)) {
|
||||
DEBUG(5, ("copy chunk no read on src handle (%s).\n",
|
||||
smb_fname_str_dbg(src_fsp->fsp_name) ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (src_fsp->is_directory) {
|
||||
DEBUG(5, ("copy chunk no read on src directory handle (%s).\n",
|
||||
smb_fname_str_dbg(src_fsp->fsp_name) ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (dst_fsp->is_directory) {
|
||||
DEBUG(5, ("copy chunk no read on dst directory handle (%s).\n",
|
||||
smb_fname_str_dbg(dst_fsp->fsp_name) ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (IS_IPC(src_fsp->conn) || IS_IPC(dst_fsp->conn)) {
|
||||
DEBUG(5, ("copy chunk no access on IPC$ handle.\n"));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (IS_PRINT(src_fsp->conn) || IS_PRINT(dst_fsp->conn)) {
|
||||
DEBUG(5, ("copy chunk no access on PRINT handle.\n"));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req);
|
||||
|
||||
static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
|
||||
@ -166,8 +107,6 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
struct tevent_req *req = NULL;
|
||||
struct fsctl_srv_copychunk_state *state = NULL;
|
||||
uint64_t src_persistent_h;
|
||||
uint64_t src_volatile_h;
|
||||
enum ndr_err_code ndr_ret;
|
||||
NTSTATUS status;
|
||||
|
||||
@ -183,6 +122,8 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
|
||||
*state = (struct fsctl_srv_copychunk_state) {
|
||||
.conn = dst_fsp->conn,
|
||||
.ev = ev,
|
||||
.ctl_code = ctl_code,
|
||||
.dst_fsp = dst_fsp,
|
||||
};
|
||||
|
||||
if (in_max_output < sizeof(struct srv_copychunk_rsp)) {
|
||||
@ -203,26 +144,8 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
/* persistent/volatile keys sent as the resume key */
|
||||
src_persistent_h = BVAL(state->cc_copy.source_key, 0);
|
||||
src_volatile_h = BVAL(state->cc_copy.source_key, 8);
|
||||
state->src_fsp = file_fsp_get(smb2req, src_persistent_h, src_volatile_h);
|
||||
if (state->src_fsp == NULL) {
|
||||
DEBUG(3, ("invalid resume key in copy chunk req\n"));
|
||||
state->status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
tevent_req_nterror(req, state->status);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->dst_fsp = dst_fsp;
|
||||
|
||||
state->status = copychunk_check_handles(ctl_code,
|
||||
state->src_fsp,
|
||||
state->dst_fsp);
|
||||
if (!NT_STATUS_IS_OK(state->status)) {
|
||||
tevent_req_nterror(req, state->status);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->token = data_blob_const(state->cc_copy.source_key,
|
||||
sizeof(state->cc_copy.source_key));
|
||||
|
||||
state->status = copychunk_check_limits(&state->cc_copy);
|
||||
if (!NT_STATUS_IS_OK(state->status)) {
|
||||
@ -272,7 +195,8 @@ static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req)
|
||||
subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn,
|
||||
state,
|
||||
state->ev,
|
||||
state->src_fsp,
|
||||
state->ctl_code,
|
||||
&state->token,
|
||||
source_off,
|
||||
state->dst_fsp,
|
||||
target_off,
|
||||
|
@ -2377,16 +2377,18 @@ NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
|
||||
struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct files_struct *src_fsp,
|
||||
off_t src_off,
|
||||
uint32_t fsctl,
|
||||
DATA_BLOB *token,
|
||||
off_t transfer_offset,
|
||||
struct files_struct *dest_fsp,
|
||||
off_t dest_off,
|
||||
off_t num,
|
||||
uint32_t flags)
|
||||
{
|
||||
VFS_FIND(offload_write_send);
|
||||
return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, src_fsp,
|
||||
src_off, dest_fsp, dest_off, num,
|
||||
return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
|
||||
token, transfer_offset,
|
||||
dest_fsp, dest_off, num,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user