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