1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_ 6 #define MOJO_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_ 7 8 #include "base/macros.h" 9 #include "build/build_config.h" 10 #include "mojo/core/scoped_process_handle.h" 11 #include "mojo/public/cpp/platform/platform_handle.h" 12 13 #if defined(OS_MACOSX) && !defined(OS_IOS) 14 #include <mach/mach.h> 15 #endif 16 17 #if defined(OS_WIN) 18 #include <windows.h> 19 #endif 20 21 namespace mojo { 22 namespace core { 23 24 // Owns a PlatformHandle which may actually belong to another process. On 25 // Windows and (sometimes) Mac, handles in a message object may take on values 26 // which only have meaning in the context of a remote process. 27 // 28 // This class provides a safe way of scoping the lifetime of such handles so 29 // that they don't leak when transmission can't be completed. 30 class PlatformHandleInTransit { 31 public: 32 PlatformHandleInTransit(); 33 explicit PlatformHandleInTransit(PlatformHandle handle); 34 PlatformHandleInTransit(PlatformHandleInTransit&&); 35 ~PlatformHandleInTransit(); 36 37 PlatformHandleInTransit& operator=(PlatformHandleInTransit&&); 38 39 // Accessor for the owned handle. Must be owned by the calling process. 40 const PlatformHandle& handle() const { 41 DCHECK(!owning_process_.is_valid()); 42 return handle_; 43 } 44 45 // Returns the process which owns this handle. If this is invalid, the handle 46 // is owned by the current process. 47 const ScopedProcessHandle& owning_process() const { return owning_process_; } 48 49 // Takes ownership of the held handle as-is. The handle must belong to the 50 // current process. 51 PlatformHandle TakeHandle(); 52 53 // Discards the handle owned by this object. The implication is that its 54 // value has been successfully communicated to the owning process and the 55 // calling process is no longer responsible for managing the handle's 56 // lifetime. 57 void CompleteTransit(); 58 59 // Transfers ownership of this (local) handle to |target_process|. 60 bool TransferToProcess(ScopedProcessHandle target_process); 61 62 #if defined(OS_WIN) 63 HANDLE remote_handle() const { return remote_handle_; } 64 65 // Returns a new local handle, with ownership of |handle| being transferred 66 // from |owning_process| to the caller. 67 static PlatformHandle TakeIncomingRemoteHandle( 68 HANDLE handle, 69 base::ProcessHandle owning_process); 70 #endif 71 72 #if defined(OS_MACOSX) && !defined(OS_IOS) 73 // Creates a special wrapper holding an unowned Mach port name. This may refer 74 // to a send or receive right in a remote task (process), and is used for 75 // cases where message must retain such an object as one of its attached 76 // handles. We're OK for now with leaking in any scenario where a lack of 77 // strict ownership could cause leakage. See https://crbug.com/855930 for more 78 // details. 79 static PlatformHandleInTransit CreateForMachPortName(mach_port_t name); 80 81 bool is_mach_port_name() const { return mach_port_name_ != MACH_PORT_NULL; } 82 mach_port_t mach_port_name() const { return mach_port_name_; } 83 #endif 84 85 private: 86 #if defined(OS_WIN) 87 // We don't use a ScopedHandle (or, by extension, PlatformHandle) here because 88 // the handle verifier expects all handle values to be owned by this process. 89 // On Windows we use |handle_| for locally owned handles and |remote_handle_| 90 // otherwise. On all other platforms we use |handle_| regardless of ownership. 91 HANDLE remote_handle_ = INVALID_HANDLE_VALUE; 92 #endif 93 94 PlatformHandle handle_; 95 ScopedProcessHandle owning_process_; 96 97 #if defined(OS_MACOSX) && !defined(OS_IOS) 98 mach_port_t mach_port_name_ = MACH_PORT_NULL; 99 #endif 100 101 DISALLOW_COPY_AND_ASSIGN(PlatformHandleInTransit); 102 }; 103 104 } // namespace core 105 } // namespace mojo 106 107 #endif // MOJO_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_ 108