Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: ipc/attachment_broker_privileged_mac.cc

Issue 2473993003: Delete IPC::ChannelPosix, IPC::ChannelWin and IPC::AttachmentBroker. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 #include "ipc/attachment_broker_privileged_mac.h"
6
7 #include <stdint.h>
8
9 #include <tuple>
10
11 #include "base/mac/mach_port_util.h"
12 #include "base/mac/scoped_mach_port.h"
13 #include "base/memory/shared_memory.h"
14 #include "base/process/port_provider_mac.h"
15 #include "base/process/process.h"
16 #include "base/synchronization/lock.h"
17 #include "ipc/attachment_broker_messages.h"
18 #include "ipc/brokerable_attachment.h"
19 #include "ipc/ipc_channel.h"
20 #include "ipc/mach_port_attachment_mac.h"
21
22 namespace IPC {
23
24 AttachmentBrokerPrivilegedMac::AttachmentBrokerPrivilegedMac(
25 base::PortProvider* port_provider)
26 : port_provider_(port_provider) {
27 port_provider_->AddObserver(this);
28 }
29
30 AttachmentBrokerPrivilegedMac::~AttachmentBrokerPrivilegedMac() {
31 port_provider_->RemoveObserver(this);
32 {
33 base::AutoLock l(precursors_lock_);
34 for (auto it : precursors_)
35 delete it.second;
36 }
37 {
38 base::AutoLock l(extractors_lock_);
39 for (auto it : extractors_)
40 delete it.second;
41 }
42 }
43
44 bool AttachmentBrokerPrivilegedMac::SendAttachmentToProcess(
45 const scoped_refptr<IPC::BrokerableAttachment>& attachment,
46 base::ProcessId destination_process) {
47 switch (attachment->GetBrokerableType()) {
48 case BrokerableAttachment::MACH_PORT: {
49 internal::MachPortAttachmentMac* mach_port_attachment =
50 static_cast<internal::MachPortAttachmentMac*>(attachment.get());
51 MachPortWireFormat wire_format =
52 mach_port_attachment->GetWireFormat(destination_process);
53 AddPrecursor(wire_format.destination_process,
54 base::mac::ScopedMachSendRight(wire_format.mach_port),
55 wire_format.attachment_id);
56 mach_port_attachment->reset_mach_port_ownership();
57 SendPrecursorsForProcess(wire_format.destination_process, true);
58 return true;
59 }
60 default:
61 NOTREACHED();
62 return false;
63 }
64 return false;
65 }
66
67 void AttachmentBrokerPrivilegedMac::DeregisterCommunicationChannel(
68 Endpoint* endpoint) {
69 AttachmentBrokerPrivileged::DeregisterCommunicationChannel(endpoint);
70
71 if (!endpoint)
72 return;
73
74 base::ProcessId pid = endpoint->GetPeerPID();
75 if (pid == base::kNullProcessId)
76 return;
77
78 {
79 base::AutoLock l(precursors_lock_);
80 auto it = precursors_.find(pid);
81 if (it != precursors_.end()) {
82 delete it->second;
83 precursors_.erase(pid);
84 }
85 }
86
87 {
88 base::AutoLock l(extractors_lock_);
89 auto it = extractors_.find(pid);
90 if (it != extractors_.end()) {
91 delete it->second;
92 extractors_.erase(pid);
93 }
94 }
95 }
96
97 void AttachmentBrokerPrivilegedMac::ReceivedPeerPid(base::ProcessId peer_pid) {
98 ProcessExtractorsForProcess(peer_pid, false);
99 SendPrecursorsForProcess(peer_pid, false);
100 }
101
102 bool AttachmentBrokerPrivilegedMac::OnMessageReceived(const Message& msg) {
103 bool handled = true;
104 switch (msg.type()) {
105 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateMachPort,
106 OnDuplicateMachPort(msg))
107 IPC_MESSAGE_UNHANDLED(handled = false)
108 }
109 return handled;
110 }
111
112 void AttachmentBrokerPrivilegedMac::OnReceivedTaskPort(
113 base::ProcessHandle process) {
114 SendPrecursorsForProcess(process, true);
115 }
116
117 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::AttachmentPrecursor(
118 const base::ProcessId& pid,
119 base::mac::ScopedMachSendRight port,
120 const BrokerableAttachment::AttachmentId& id)
121 : pid_(pid), port_(port.release()), id_(id) {}
122
123 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::~AttachmentPrecursor() {}
124
125 base::mac::ScopedMachSendRight
126 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::TakePort() {
127 return base::mac::ScopedMachSendRight(port_.release());
128 }
129
130 AttachmentBrokerPrivilegedMac::AttachmentExtractor::AttachmentExtractor(
131 const base::ProcessId& source_pid,
132 const base::ProcessId& dest_pid,
133 mach_port_name_t port,
134 const BrokerableAttachment::AttachmentId& id)
135 : source_pid_(source_pid),
136 dest_pid_(dest_pid),
137 port_to_extract_(port),
138 id_(id) {}
139
140 AttachmentBrokerPrivilegedMac::AttachmentExtractor::~AttachmentExtractor() {}
141
142 void AttachmentBrokerPrivilegedMac::OnDuplicateMachPort(
143 const IPC::Message& message) {
144 DCHECK_NE(0, message.get_sender_pid());
145 AttachmentBrokerMsg_DuplicateMachPort::Param param;
146 if (!AttachmentBrokerMsg_DuplicateMachPort::Read(&message, &param)) {
147 LogError(ERROR_PARSE_DUPLICATE_MACH_PORT_MESSAGE);
148 return;
149 }
150 IPC::internal::MachPortAttachmentMac::WireFormat wire_format =
151 std::get<0>(param);
152
153 if (wire_format.destination_process == base::kNullProcessId) {
154 LogError(NO_DESTINATION);
155 return;
156 }
157
158 AddExtractor(message.get_sender_pid(), wire_format.destination_process,
159 wire_format.mach_port, wire_format.attachment_id);
160 ProcessExtractorsForProcess(message.get_sender_pid(), true);
161 }
162
163 void AttachmentBrokerPrivilegedMac::RoutePrecursorToSelf(
164 AttachmentPrecursor* precursor) {
165 DCHECK_EQ(base::Process::Current().Pid(), precursor->pid());
166
167 // Intentionally leak the port, since the attachment takes ownership.
168 internal::MachPortAttachmentMac::WireFormat wire_format(
169 precursor->TakePort().release(), precursor->pid(), precursor->id());
170 scoped_refptr<BrokerableAttachment> attachment(
171 new internal::MachPortAttachmentMac(wire_format));
172 HandleReceivedAttachment(attachment);
173 }
174
175 bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother(
176 const MachPortWireFormat& wire_format) {
177 DCHECK_NE(wire_format.destination_process, base::Process::Current().Pid());
178
179 // Another process is the destination.
180 base::ProcessId dest = wire_format.destination_process;
181 base::AutoLock auto_lock(*get_lock());
182 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
183 GetSenderWithProcessId(dest);
184 if (!pair.first) {
185 // The extractor was successfully processed, which implies that the
186 // communication channel was established. This implies that the
187 // communication was taken down in the interim.
188 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: "
189 << dest;
190 LogError(DESTINATION_NOT_FOUND);
191 return false;
192 }
193
194 LogError(DESTINATION_FOUND);
195 SendMessageToEndpoint(
196 pair, new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format));
197 return true;
198 }
199
200 base::mac::ScopedMachSendRight AttachmentBrokerPrivilegedMac::ExtractNamedRight(
201 mach_port_t task_port,
202 mach_port_name_t named_right) {
203 if (named_right == MACH_PORT_NULL)
204 return base::mac::ScopedMachSendRight(MACH_PORT_NULL);
205
206 mach_port_t extracted_right = MACH_PORT_NULL;
207 mach_msg_type_name_t extracted_right_type;
208 kern_return_t kr =
209 mach_port_extract_right(task_port, named_right, MACH_MSG_TYPE_MOVE_SEND,
210 &extracted_right, &extracted_right_type);
211 if (kr != KERN_SUCCESS) {
212 LogError(ERROR_EXTRACT_SOURCE_RIGHT);
213 return base::mac::ScopedMachSendRight(MACH_PORT_NULL);
214 }
215
216 DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND),
217 extracted_right_type);
218
219 return base::mac::ScopedMachSendRight(extracted_right);
220 }
221
222 AttachmentBrokerPrivilegedMac::MachPortWireFormat
223 AttachmentBrokerPrivilegedMac::CopyWireFormat(
224 const MachPortWireFormat& wire_format,
225 uint32_t mach_port) {
226 return MachPortWireFormat(mach_port, wire_format.destination_process,
227 wire_format.attachment_id);
228 }
229
230 void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess(
231 base::ProcessId pid,
232 bool store_on_failure) {
233 base::AutoLock l(precursors_lock_);
234 auto it = precursors_.find(pid);
235 if (it == precursors_.end())
236 return;
237
238 // Whether this process is the destination process.
239 bool to_self = pid == base::GetCurrentProcId();
240
241 if (!to_self) {
242 base::AutoLock auto_lock(*get_lock());
243 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
244 GetSenderWithProcessId(pid);
245 if (!pair.first) {
246 // Try again later.
247 if (store_on_failure)
248 return;
249
250 // If there is no sender, then permanently fail.
251 LogError(DESTINATION_NOT_FOUND);
252 delete it->second;
253 precursors_.erase(it);
254 return;
255 }
256 }
257
258 mach_port_t task_port = port_provider_->TaskForPid(pid);
259
260 // It's possible that the destination process has not yet provided the
261 // privileged process with its task port.
262 if (!to_self && task_port == MACH_PORT_NULL)
263 return;
264
265 while (!it->second->empty()) {
266 auto precursor_it = it->second->begin();
267 if (to_self) {
268 RoutePrecursorToSelf(*precursor_it);
269 } else {
270 if (!SendPrecursor(*precursor_it, task_port))
271 break;
272 }
273 it->second->erase(precursor_it);
274 }
275
276 delete it->second;
277 precursors_.erase(it);
278 }
279
280 bool AttachmentBrokerPrivilegedMac::SendPrecursor(
281 AttachmentPrecursor* precursor,
282 mach_port_t task_port) {
283 DCHECK(task_port);
284 internal::MachPortAttachmentMac::WireFormat wire_format(
285 MACH_PORT_NULL, precursor->pid(), precursor->id());
286 base::mac::ScopedMachSendRight port_to_insert = precursor->TakePort();
287 mach_port_name_t intermediate_port = MACH_PORT_NULL;
288 if (port_to_insert.get() != MACH_PORT_NULL) {
289 base::MachCreateError error_code;
290 intermediate_port = base::CreateIntermediateMachPort(
291 task_port, base::mac::ScopedMachSendRight(port_to_insert.release()),
292 &error_code);
293 if (intermediate_port == MACH_PORT_NULL) {
294 UMAError uma_error;
295 switch (error_code) {
296 case base::MachCreateError::ERROR_MAKE_RECEIVE_PORT:
297 uma_error = ERROR_MAKE_RECEIVE_PORT;
298 break;
299 case base::MachCreateError::ERROR_SET_ATTRIBUTES:
300 uma_error = ERROR_SET_ATTRIBUTES;
301 break;
302 case base::MachCreateError::ERROR_EXTRACT_DEST_RIGHT:
303 uma_error = ERROR_EXTRACT_DEST_RIGHT;
304 break;
305 case base::MachCreateError::ERROR_SEND_MACH_PORT:
306 uma_error = ERROR_SEND_MACH_PORT;
307 break;
308 }
309 LogError(uma_error);
310 }
311 }
312 return RouteWireFormatToAnother(
313 CopyWireFormat(wire_format, intermediate_port));
314 }
315
316 void AttachmentBrokerPrivilegedMac::AddPrecursor(
317 base::ProcessId pid,
318 base::mac::ScopedMachSendRight port,
319 const BrokerableAttachment::AttachmentId& id) {
320 base::AutoLock l(precursors_lock_);
321 auto it = precursors_.find(pid);
322 if (it == precursors_.end())
323 precursors_[pid] = new ScopedVector<AttachmentPrecursor>;
324
325 precursors_[pid]->push_back(new AttachmentPrecursor(
326 pid, base::mac::ScopedMachSendRight(port.release()), id));
327 }
328
329 void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess(
330 base::ProcessId pid,
331 bool store_on_failure) {
332 base::AutoLock l(extractors_lock_);
333 auto it = extractors_.find(pid);
334 if (it == extractors_.end())
335 return;
336
337 {
338 base::AutoLock auto_lock(*get_lock());
339 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
340 GetSenderWithProcessId(pid);
341 if (!pair.first) {
342 // If there is no sender, then the communication channel with the source
343 // process has not yet been established. Try again later.
344 if (store_on_failure)
345 return;
346
347 // There is no sender. Permanently fail.
348 LogError(ERROR_SOURCE_NOT_FOUND);
349 delete it->second;
350 extractors_.erase(it);
351 return;
352 }
353 }
354
355 mach_port_t task_port = port_provider_->TaskForPid(pid);
356
357 // It's possible that the source process has not yet provided the privileged
358 // process with its task port.
359 if (task_port == MACH_PORT_NULL)
360 return;
361
362 while (!it->second->empty()) {
363 auto extractor_it = it->second->begin();
364 ProcessExtractor(*extractor_it, task_port);
365 it->second->erase(extractor_it);
366 }
367
368 delete it->second;
369 extractors_.erase(it);
370 }
371
372 void AttachmentBrokerPrivilegedMac::ProcessExtractor(
373 AttachmentExtractor* extractor,
374 mach_port_t task_port) {
375 DCHECK(task_port);
376 base::mac::ScopedMachSendRight send_right =
377 ExtractNamedRight(task_port, extractor->port());
378 AddPrecursor(extractor->dest_pid(),
379 base::mac::ScopedMachSendRight(send_right.release()),
380 extractor->id());
381 SendPrecursorsForProcess(extractor->dest_pid(), true);
382 }
383
384 void AttachmentBrokerPrivilegedMac::AddExtractor(
385 base::ProcessId source_pid,
386 base::ProcessId dest_pid,
387 mach_port_name_t port,
388 const BrokerableAttachment::AttachmentId& id) {
389 base::AutoLock l(extractors_lock_);
390 DCHECK_NE(base::GetCurrentProcId(), source_pid);
391
392 auto it = extractors_.find(source_pid);
393 if (it == extractors_.end())
394 extractors_[source_pid] = new ScopedVector<AttachmentExtractor>;
395
396 extractors_[source_pid]->push_back(
397 new AttachmentExtractor(source_pid, dest_pid, port, id));
398 }
399
400 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/attachment_broker_privileged_mac.h ('k') | ipc/attachment_broker_privileged_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698