| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 IPC_ATTACHMENT_BROKER_PRIVILEGED_MAC_H_ | |
| 6 #define IPC_ATTACHMENT_BROKER_PRIVILEGED_MAC_H_ | |
| 7 | |
| 8 #include <mach/mach.h> | |
| 9 #include <stdint.h> | |
| 10 | |
| 11 #include <map> | |
| 12 | |
| 13 #include "base/gtest_prod_util.h" | |
| 14 #include "base/mac/scoped_mach_port.h" | |
| 15 #include "base/macros.h" | |
| 16 #include "base/memory/scoped_vector.h" | |
| 17 #include "base/process/port_provider_mac.h" | |
| 18 #include "base/synchronization/lock.h" | |
| 19 #include "ipc/attachment_broker_privileged.h" | |
| 20 #include "ipc/ipc_export.h" | |
| 21 #include "ipc/mach_port_attachment_mac.h" | |
| 22 | |
| 23 namespace base { | |
| 24 class PortProvider; | |
| 25 } // namespace base | |
| 26 | |
| 27 namespace IPC { | |
| 28 | |
| 29 // This class is a concrete subclass of AttachmentBrokerPrivileged for the | |
| 30 // OSX platform. | |
| 31 // | |
| 32 // An example of the typical process by which a Mach port gets brokered. | |
| 33 // Definitions: | |
| 34 // 1. Let there be three processes P1, U2, U3. P1 is privileged. | |
| 35 // 2. U2 wants to send a Mach port M2 to U3. If this port is inserted into P1, | |
| 36 // it will be called M1. If it is inserted into U3, it will be called M3. | |
| 37 // 3. name() returns a serializable representation of a Mach port that can be | |
| 38 // passed over chrome IPC. | |
| 39 // 4. pid() returns the process id of a process. | |
| 40 // | |
| 41 // Process: | |
| 42 // 1. U2 sends a AttachmentBrokerMsg_DuplicateMachPort message to P1. The | |
| 43 // message contains name(M2), and pid(U3). | |
| 44 // 2. P1 extracts M2 into its own namespace, making M1. | |
| 45 // 3. P1 makes a new Mach port R in U3. | |
| 46 // 4. P1 sends a mach_msg with M1 to R. | |
| 47 // 5. P1 sends name(R) to U3. | |
| 48 // 6. U3 retrieves the queued message from R. The kernel automatically | |
| 49 // translates M1 into the namespace of U3, making M3. | |
| 50 // | |
| 51 // The logic of this class is a little bit more complex becauese any or all of | |
| 52 // P1, U2 and U3 may be the same, and depending on the exact configuration, | |
| 53 // the creation of R may not be necessary. | |
| 54 // | |
| 55 // For the rest of this file, and the corresponding implementation file, R will | |
| 56 // be called the "intermediate Mach port" and M3 the "final Mach port". | |
| 57 class IPC_EXPORT AttachmentBrokerPrivilegedMac | |
| 58 : public AttachmentBrokerPrivileged, | |
| 59 public base::PortProvider::Observer { | |
| 60 public: | |
| 61 explicit AttachmentBrokerPrivilegedMac(base::PortProvider* port_provider); | |
| 62 ~AttachmentBrokerPrivilegedMac() override; | |
| 63 | |
| 64 // IPC::AttachmentBroker overrides. | |
| 65 bool SendAttachmentToProcess( | |
| 66 const scoped_refptr<IPC::BrokerableAttachment>& attachment, | |
| 67 base::ProcessId destination_process) override; | |
| 68 void DeregisterCommunicationChannel(Endpoint* endpoint) override; | |
| 69 void ReceivedPeerPid(base::ProcessId peer_pid) override; | |
| 70 | |
| 71 // IPC::Listener overrides. | |
| 72 bool OnMessageReceived(const Message& message) override; | |
| 73 | |
| 74 // base::PortProvider::Observer override. | |
| 75 void OnReceivedTaskPort(base::ProcessHandle process) override; | |
| 76 | |
| 77 private: | |
| 78 FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerPrivilegedMacMultiProcessTest, | |
| 79 InsertRight); | |
| 80 FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerPrivilegedMacMultiProcessTest, | |
| 81 InsertSameRightTwice); | |
| 82 FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerPrivilegedMacMultiProcessTest, | |
| 83 InsertTwoRights); | |
| 84 using MachPortWireFormat = internal::MachPortAttachmentMac::WireFormat; | |
| 85 | |
| 86 // Contains all the information necessary to broker an attachment into a | |
| 87 // destination process. The only thing that prevents an AttachmentPrecusor | |
| 88 // from being immediately processed is if |port_provider_| does not yet have a | |
| 89 // task port for |pid|. | |
| 90 class IPC_EXPORT AttachmentPrecursor { | |
| 91 public: | |
| 92 AttachmentPrecursor(const base::ProcessId& pid, | |
| 93 base::mac::ScopedMachSendRight port_to_insert, | |
| 94 const BrokerableAttachment::AttachmentId& id); | |
| 95 ~AttachmentPrecursor(); | |
| 96 | |
| 97 // Caller takes ownership of |port_|. | |
| 98 base::mac::ScopedMachSendRight TakePort(); | |
| 99 | |
| 100 base::ProcessId pid() const { return pid_; } | |
| 101 const BrokerableAttachment::AttachmentId id() const { return id_; } | |
| 102 | |
| 103 private: | |
| 104 // The pid of the destination process. | |
| 105 const base::ProcessId pid_; | |
| 106 // The final Mach port, as per definition at the top of this file. | |
| 107 base::mac::ScopedMachSendRight port_; | |
| 108 // The id of the attachment. | |
| 109 const BrokerableAttachment::AttachmentId id_; | |
| 110 DISALLOW_COPY_AND_ASSIGN(AttachmentPrecursor); | |
| 111 }; | |
| 112 | |
| 113 // Contains all the information necessary to extract a send right and create | |
| 114 // an AttachmentPrecursor. The only thing that prevents an AttachmentExtractor | |
| 115 // from being immediately processed is if |port_provider_| does not yet have a | |
| 116 // task port for |source_pid|. | |
| 117 class IPC_EXPORT AttachmentExtractor { | |
| 118 public: | |
| 119 AttachmentExtractor(const base::ProcessId& source_pid, | |
| 120 const base::ProcessId& dest_pid, | |
| 121 mach_port_name_t port, | |
| 122 const BrokerableAttachment::AttachmentId& id); | |
| 123 ~AttachmentExtractor(); | |
| 124 | |
| 125 base::ProcessId source_pid() const { return source_pid_; } | |
| 126 base::ProcessId dest_pid() const { return dest_pid_; } | |
| 127 mach_port_name_t port() const { return port_to_extract_; } | |
| 128 const BrokerableAttachment::AttachmentId id() const { return id_; } | |
| 129 | |
| 130 private: | |
| 131 const base::ProcessId source_pid_; | |
| 132 const base::ProcessId dest_pid_; | |
| 133 mach_port_name_t port_to_extract_; | |
| 134 const BrokerableAttachment::AttachmentId id_; | |
| 135 }; | |
| 136 | |
| 137 // IPC message handlers. | |
| 138 void OnDuplicateMachPort(const Message& message); | |
| 139 | |
| 140 // Duplicates the Mach port referenced from |wire_format| from | |
| 141 // |source_process| into |wire_format|'s destination process. | |
| 142 MachPortWireFormat DuplicateMachPort(const MachPortWireFormat& wire_format, | |
| 143 base::ProcessId source_process); | |
| 144 | |
| 145 // Extracts a copy of the send right to |named_right| from |task_port|. | |
| 146 // Returns MACH_PORT_NULL on error. | |
| 147 base::mac::ScopedMachSendRight ExtractNamedRight( | |
| 148 mach_port_t task_port, | |
| 149 mach_port_name_t named_right); | |
| 150 | |
| 151 // Copies an existing |wire_format|, but substitutes in a different mach port. | |
| 152 MachPortWireFormat CopyWireFormat(const MachPortWireFormat& wire_format, | |
| 153 uint32_t mach_port); | |
| 154 | |
| 155 // |wire_format.destination_process| must be this process. | |
| 156 // |wire_format.mach_port| must be the final Mach port. | |
| 157 // Consumes a reference to |wire_format.mach_port|, as ownership is implicitly | |
| 158 // passed to the consumer of the Chrome IPC message. | |
| 159 // Makes an attachment, queues it, and notifies the observers. | |
| 160 void RoutePrecursorToSelf(AttachmentPrecursor* precursor); | |
| 161 | |
| 162 // |wire_format.destination_process| must be another process. | |
| 163 // |wire_format.mach_port| must be the intermediate Mach port. | |
| 164 // Ownership of |wire_format.mach_port| is implicitly passed to the process | |
| 165 // that receives the Chrome IPC message. | |
| 166 // Returns |false| on irrecoverable error. | |
| 167 bool RouteWireFormatToAnother(const MachPortWireFormat& wire_format); | |
| 168 | |
| 169 // Atempts to broker all precursors whose destination is |pid|. Has no effect | |
| 170 // if |port_provider_| does not have the task port for |pid|. | |
| 171 // If a communication channel has not been established from the destination | |
| 172 // process, and |store_on_failure| is true, then the precursor is kept for | |
| 173 // later reuse. If |store_on_failure| is false, then the precursor is deleted. | |
| 174 void SendPrecursorsForProcess(base::ProcessId pid, bool store_on_failure); | |
| 175 | |
| 176 // Brokers a single precursor into the task represented by |task_port|. | |
| 177 // Returns |false| on irrecoverable error. | |
| 178 bool SendPrecursor(AttachmentPrecursor* precursor, mach_port_t task_port); | |
| 179 | |
| 180 // Add a precursor to |precursors_|. Takes ownership of |port|. | |
| 181 void AddPrecursor(base::ProcessId pid, | |
| 182 base::mac::ScopedMachSendRight port, | |
| 183 const BrokerableAttachment::AttachmentId& id); | |
| 184 | |
| 185 // Atempts to process all extractors whose source is |pid|. Has no effect | |
| 186 // if |port_provider_| does not have the task port for |pid|. | |
| 187 // If a communication channel has not been established from the source | |
| 188 // process, and |store_on_failure| is true, then the extractor is kept for | |
| 189 // later reuse. If |store_on_failure| is false, then the extractor is deleted. | |
| 190 void ProcessExtractorsForProcess(base::ProcessId pid, bool store_on_failure); | |
| 191 | |
| 192 // Processes a single extractor whose source pid is represented by | |
| 193 // |task_port|. | |
| 194 void ProcessExtractor(AttachmentExtractor* extractor, mach_port_t task_port); | |
| 195 | |
| 196 // Add an extractor to |extractors_|. | |
| 197 void AddExtractor(base::ProcessId source_pid, | |
| 198 base::ProcessId dest_pid, | |
| 199 mach_port_name_t port, | |
| 200 const BrokerableAttachment::AttachmentId& id); | |
| 201 | |
| 202 // The port provider must live at least as long as the AttachmentBroker. | |
| 203 base::PortProvider* port_provider_; | |
| 204 | |
| 205 // For each ProcessId, a vector of precursors that are waiting to be | |
| 206 // sent. | |
| 207 std::map<base::ProcessId, ScopedVector<AttachmentPrecursor>*> precursors_; | |
| 208 base::Lock precursors_lock_; | |
| 209 | |
| 210 // For each ProcessId, a vector of extractors that are waiting to be | |
| 211 // processed. | |
| 212 std::map<base::ProcessId, ScopedVector<AttachmentExtractor>*> extractors_; | |
| 213 base::Lock extractors_lock_; | |
| 214 | |
| 215 DISALLOW_COPY_AND_ASSIGN(AttachmentBrokerPrivilegedMac); | |
| 216 }; | |
| 217 | |
| 218 } // namespace IPC | |
| 219 | |
| 220 #endif // IPC_ATTACHMENT_BROKER_PRIVILEGED_MAC_H_ | |
| OLD | NEW |