vfs_btrfs: make use of become_user_by_fsp() in order to switch between src and dst fsp
[samba.git] / source3 / modules / vfs_btrfs.c
index 515859d6b90a66d61e1b97905283e7eca2ce6d0d..a11cb66d8e7820c92472e29b5ad5a606067d4f79 100644 (file)
@@ -199,7 +199,26 @@ static NTSTATUS btrfs_offload_read_recv(struct tevent_req *req,
 struct btrfs_offload_write_state {
        struct vfs_handle_struct *handle;
        off_t copied;
+       bool need_unbecome_user;
 };
+
+static void btrfs_offload_write_cleanup(struct tevent_req *req,
+                                       enum tevent_req_state req_state)
+{
+       struct btrfs_offload_write_state *state =
+               tevent_req_data(req,
+               struct btrfs_offload_write_state);
+       bool ok;
+
+       if (!state->need_unbecome_user) {
+               return;
+       }
+
+       ok = unbecome_user();
+       SMB_ASSERT(ok);
+       state->need_unbecome_user = false;
+}
+
 static void btrfs_offload_write_done(struct tevent_req *subreq);
 
 static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *handle,
@@ -224,6 +243,7 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
        bool handle_offload_write = true;
        bool do_locking = false;
        NTSTATUS status;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct btrfs_offload_write_state);
@@ -233,6 +253,8 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
 
        state->handle = handle;
 
+       tevent_req_set_cleanup_fn(req, btrfs_offload_write_cleanup);
+
        status = vfs_offload_token_db_fetch_fsp(btrfs_offload_ctx,
                                                token, &src_fsp);
        if (tevent_req_nterror(req, status)) {
@@ -289,6 +311,13 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
                return tevent_req_post(req, ev);
        }
 
+       ok = become_user_by_fsp(src_fsp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+               return tevent_req_post(req, ev);
+       }
+       state->need_unbecome_user = true;
+
        status = vfs_stat_fsp(src_fsp);
        if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
@@ -307,17 +336,24 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han
                                        num,
                                        READ_LOCK,
                                        &src_lck);
+               if (!SMB_VFS_STRICT_LOCK_CHECK(src_fsp->conn, src_fsp, &src_lck)) {
+                       tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+                       return tevent_req_post(req, ev);
+               }
+       }
+
+       ok = unbecome_user();
+       SMB_ASSERT(ok);
+       state->need_unbecome_user = false;
+
+       if (do_locking) {
                init_strict_lock_struct(dest_fsp,
-                                      dest_fsp->op->global->open_persistent_id,
+                                       dest_fsp->op->global->open_persistent_id,
                                        dest_off,
                                        num,
                                        WRITE_LOCK,
                                        &dest_lck);
 
-               if (!SMB_VFS_STRICT_LOCK_CHECK(src_fsp->conn, src_fsp, &src_lck)) {
-                       tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
-                       return tevent_req_post(req, ev);
-               }
                if (!SMB_VFS_STRICT_LOCK_CHECK(dest_fsp->conn, dest_fsp, &dest_lck)) {
                        tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        return tevent_req_post(req, ev);