1 // Copyright 2016 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #pragma once
8 
9 #include <zircon/types.h>
10 #include <zircon/syscalls/types.h>
11 #include <lib/user_copy/user_ptr.h>
12 
13 // Forward declaration so it can be used in abigen-generated sys_* prototypes.
14 class user_out_handle;
15 
16 #define ZX_SYSCALL_PARAM_ATTR(x)
17 #include <zircon/syscall-definitions.h>
18 
19 #include <object/handle.h>
20 #include <object/process_dispatcher.h>
21 
22 // This is the type of handle result parameters in system call
23 // implementation functions (sys_*).  abigen recognizes return values of
24 // type zx_handle_t and converts them into user_out_handle* instead of into
25 // user_out_ptr<zx_handle_t>.  System call implementation functions use the
26 // make, dup, or transfer method to turn a Dispatcher pointer or another
27 // handle into a handle received by the user.
28 class user_out_handle final {
29 public:
make(fbl::RefPtr<Dispatcher> dispatcher,zx_rights_t rights)30     zx_status_t make(fbl::RefPtr<Dispatcher> dispatcher, zx_rights_t rights) {
31         h_ = Handle::Make(ktl::move(dispatcher), rights);
32         return h_ ? ZX_OK : ZX_ERR_NO_MEMORY;
33     }
34 
dup(Handle * source,zx_rights_t rights)35     zx_status_t dup(Handle* source, zx_rights_t rights) {
36         h_ = Handle::Dup(source, rights);
37         return h_ ? ZX_OK : ZX_ERR_NO_MEMORY;
38     }
39 
transfer(HandleOwner && source)40     zx_status_t transfer(HandleOwner&& source) {
41         h_.swap(source);
42         return ZX_OK;
43     }
44 
45     // These methods are called by the abigen-generated wrapper_* functions
46     // (syscall-kernel-wrappers.inc).  See KernelWrapperGenerator::syscall.
47 
begin_copyout(ProcessDispatcher * current_process,user_out_ptr<zx_handle_t> out)48     bool begin_copyout(ProcessDispatcher* current_process,
49                        user_out_ptr<zx_handle_t> out) const {
50         if (h_)
51             return out.copy_to_user(current_process->MapHandleToValue(h_));
52         return false;
53     }
54 
finish_copyout(ProcessDispatcher * current_process)55     void finish_copyout(ProcessDispatcher* current_process) {
56         if (h_)
57             current_process->AddHandle(ktl::move(h_));
58     }
59 
60 private:
61     HandleOwner h_;
62 };
63