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 |