vfs_default: make use of change_to_user_by_fsp() in order to switch between src and...
authorStefan Metzmacher <metze@samba.org>
Wed, 23 May 2018 10:03:02 +0000 (12:03 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 18 Jun 2018 06:59:18 +0000 (08:59 +0200)
This may matter if at least one share uses "force user".

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/modules/vfs_default.c

index 58df47ee6b4cf87f9e487a9e154244b016361851..baeb285eeb3480483a2717760f05c648aee4a977 100644 (file)
@@ -1598,6 +1598,22 @@ struct vfswrap_offload_write_state {
        size_t next_io_size;
 };
 
+static void vfswrap_offload_write_cleanup(struct tevent_req *req,
+                                         enum tevent_req_state req_state)
+{
+       struct vfswrap_offload_write_state *state = tevent_req_data(
+               req, struct vfswrap_offload_write_state);
+       bool ok;
+
+       if (state->dst_fsp == NULL) {
+               return;
+       }
+
+       ok = change_to_user_by_fsp(state->dst_fsp);
+       SMB_ASSERT(ok);
+       state->dst_fsp = NULL;
+}
+
 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
 
 static struct tevent_req *vfswrap_offload_write_send(
@@ -1616,6 +1632,7 @@ static struct tevent_req *vfswrap_offload_write_send(
        size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
        files_struct *src_fsp = NULL;
        NTSTATUS status;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct vfswrap_offload_write_state);
@@ -1633,6 +1650,8 @@ static struct tevent_req *vfswrap_offload_write_send(
                .remaining = to_copy,
        };
 
+       tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
+
        switch (fsctl) {
        case FSCTL_SRV_COPYCHUNK:
        case FSCTL_SRV_COPYCHUNK_WRITE:
@@ -1676,6 +1695,12 @@ static struct tevent_req *vfswrap_offload_write_send(
                return tevent_req_post(req, ev);
        }
 
+       ok = change_to_user_by_fsp(src_fsp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+               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);
@@ -1719,6 +1744,10 @@ static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
        struct lock_struct read_lck;
        bool ok;
 
+       /*
+        * This is called under the context of state->src_fsp.
+        */
+
        state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
 
        init_strict_lock_struct(state->src_fsp,
@@ -1778,6 +1807,12 @@ static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
 
        state->src_off += nread;
 
+       ok = change_to_user_by_fsp(state->dst_fsp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+
        init_strict_lock_struct(state->dst_fsp,
                                state->dst_fsp->op->global->open_persistent_id,
                                state->dst_off,
@@ -1815,6 +1850,7 @@ static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
        struct vfs_aio_state aio_state;
        ssize_t nwritten;
        NTSTATUS status;
+       bool ok;
 
        nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
        TALLOC_FREE(subreq);
@@ -1842,6 +1878,12 @@ static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
                return;
        }
 
+       ok = change_to_user_by_fsp(state->src_fsp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+
        status = vfswrap_offload_write_loop(req);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);