OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ipc/attachment_broker_privileged_mac.h" | 5 #include "ipc/attachment_broker_privileged_mac.h" |
6 | 6 |
7 #include "base/mac/scoped_mach_port.h" | 7 #include "base/mac/scoped_mach_port.h" |
8 #include "base/memory/shared_memory.h" | 8 #include "base/memory/shared_memory.h" |
9 #include "base/process/port_provider_mac.h" | 9 #include "base/process/port_provider_mac.h" |
10 #include "base/process/process.h" | 10 #include "base/process/process.h" |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 SendPrecursorsForProcess(wire_format.destination_process); | 89 SendPrecursorsForProcess(wire_format.destination_process); |
90 return true; | 90 return true; |
91 } | 91 } |
92 default: | 92 default: |
93 NOTREACHED(); | 93 NOTREACHED(); |
94 return false; | 94 return false; |
95 } | 95 } |
96 return false; | 96 return false; |
97 } | 97 } |
98 | 98 |
| 99 void AttachmentBrokerPrivilegedMac::DeregisterCommunicationChannel( |
| 100 Endpoint* endpoint) { |
| 101 AttachmentBrokerPrivileged::DeregisterCommunicationChannel(endpoint); |
| 102 |
| 103 if (!endpoint) |
| 104 return; |
| 105 |
| 106 base::ProcessId pid = endpoint->GetPeerPID(); |
| 107 if (pid == base::kNullProcessId) |
| 108 return; |
| 109 |
| 110 { |
| 111 base::AutoLock l(precursors_lock_); |
| 112 auto it = precursors_.find(pid); |
| 113 if (it != precursors_.end()) { |
| 114 delete it->second; |
| 115 precursors_.erase(pid); |
| 116 } |
| 117 } |
| 118 |
| 119 { |
| 120 base::AutoLock l(extractors_lock_); |
| 121 auto it = extractors_.find(pid); |
| 122 if (it != extractors_.end()) { |
| 123 delete it->second; |
| 124 extractors_.erase(pid); |
| 125 } |
| 126 } |
| 127 } |
| 128 |
99 bool AttachmentBrokerPrivilegedMac::OnMessageReceived(const Message& msg) { | 129 bool AttachmentBrokerPrivilegedMac::OnMessageReceived(const Message& msg) { |
100 bool handled = true; | 130 bool handled = true; |
101 switch (msg.type()) { | 131 switch (msg.type()) { |
102 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateMachPort, | 132 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateMachPort, |
103 OnDuplicateMachPort(msg)) | 133 OnDuplicateMachPort(msg)) |
104 IPC_MESSAGE_UNHANDLED(handled = false) | 134 IPC_MESSAGE_UNHANDLED(handled = false) |
105 } | 135 } |
106 return handled; | 136 return handled; |
107 } | 137 } |
108 | 138 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 DCHECK_EQ(base::Process::Current().Pid(), precursor->pid()); | 192 DCHECK_EQ(base::Process::Current().Pid(), precursor->pid()); |
163 | 193 |
164 // Intentionally leak the port, since the attachment takes ownership. | 194 // Intentionally leak the port, since the attachment takes ownership. |
165 internal::MachPortAttachmentMac::WireFormat wire_format( | 195 internal::MachPortAttachmentMac::WireFormat wire_format( |
166 precursor->TakePort().release(), precursor->pid(), precursor->id()); | 196 precursor->TakePort().release(), precursor->pid(), precursor->id()); |
167 scoped_refptr<BrokerableAttachment> attachment( | 197 scoped_refptr<BrokerableAttachment> attachment( |
168 new internal::MachPortAttachmentMac(wire_format)); | 198 new internal::MachPortAttachmentMac(wire_format)); |
169 HandleReceivedAttachment(attachment); | 199 HandleReceivedAttachment(attachment); |
170 } | 200 } |
171 | 201 |
172 void AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother( | 202 bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother( |
173 const MachPortWireFormat& wire_format) { | 203 const MachPortWireFormat& wire_format) { |
174 DCHECK_NE(wire_format.destination_process, base::Process::Current().Pid()); | 204 DCHECK_NE(wire_format.destination_process, base::Process::Current().Pid()); |
175 | 205 |
176 // Another process is the destination. | 206 // Another process is the destination. |
177 base::ProcessId dest = wire_format.destination_process; | 207 base::ProcessId dest = wire_format.destination_process; |
178 Sender* sender = GetSenderWithProcessId(dest); | 208 Sender* sender = GetSenderWithProcessId(dest); |
179 if (!sender) { | 209 if (!sender) { |
180 // Assuming that this message was not sent from a malicious process, the | 210 // Assuming that this message was not sent from a malicious process, the |
181 // channel endpoint that would have received this message will block | 211 // channel endpoint that would have received this message will block |
182 // forever. | 212 // forever. |
183 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: " | 213 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: " |
184 << dest; | 214 << dest; |
185 LogError(DESTINATION_NOT_FOUND); | 215 LogError(DESTINATION_NOT_FOUND); |
186 return; | 216 return false; |
187 } | 217 } |
188 | 218 |
189 LogError(DESTINATION_FOUND); | 219 LogError(DESTINATION_FOUND); |
190 sender->Send(new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format)); | 220 sender->Send(new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format)); |
| 221 return true; |
191 } | 222 } |
192 | 223 |
193 mach_port_name_t AttachmentBrokerPrivilegedMac::CreateIntermediateMachPort( | 224 mach_port_name_t AttachmentBrokerPrivilegedMac::CreateIntermediateMachPort( |
194 mach_port_t task_port, | 225 mach_port_t task_port, |
195 base::mac::ScopedMachSendRight port_to_insert) { | 226 base::mac::ScopedMachSendRight port_to_insert) { |
196 DCHECK_NE(mach_task_self(), task_port); | 227 DCHECK_NE(mach_task_self(), task_port); |
197 DCHECK_NE(static_cast<mach_port_name_t>(MACH_PORT_NULL), task_port); | 228 DCHECK_NE(static_cast<mach_port_name_t>(MACH_PORT_NULL), task_port); |
198 | 229 |
199 // Make a port with receive rights in the destination task. | 230 // Make a port with receive rights in the destination task. |
200 mach_port_name_t endpoint; | 231 mach_port_name_t endpoint; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 LogError(ERROR_SEND_MACH_PORT); | 269 LogError(ERROR_SEND_MACH_PORT); |
239 mach_port_deallocate(task_port, endpoint); | 270 mach_port_deallocate(task_port, endpoint); |
240 return MACH_PORT_NULL; | 271 return MACH_PORT_NULL; |
241 } | 272 } |
242 | 273 |
243 // Endpoint is intentionally leaked into the destination task. An IPC must be | 274 // Endpoint is intentionally leaked into the destination task. An IPC must be |
244 // sent to the destination task so that it can clean up this port. | 275 // sent to the destination task so that it can clean up this port. |
245 return endpoint; | 276 return endpoint; |
246 } | 277 } |
247 | 278 |
248 base::mac::ScopedMachSendRight AttachmentBrokerPrivilegedMac::AcquireSendRight( | |
249 base::ProcessId pid, | |
250 mach_port_name_t named_right) { | |
251 if (pid == base::GetCurrentProcId()) { | |
252 kern_return_t kr = mach_port_mod_refs(mach_task_self(), named_right, | |
253 MACH_PORT_RIGHT_SEND, 1); | |
254 if (kr != KERN_SUCCESS) | |
255 return base::mac::ScopedMachSendRight(MACH_PORT_NULL); | |
256 return base::mac::ScopedMachSendRight(named_right); | |
257 } | |
258 | |
259 mach_port_t task_port = port_provider_->TaskForPid(pid); | |
260 return ExtractNamedRight(task_port, named_right); | |
261 } | |
262 | |
263 base::mac::ScopedMachSendRight AttachmentBrokerPrivilegedMac::ExtractNamedRight( | 279 base::mac::ScopedMachSendRight AttachmentBrokerPrivilegedMac::ExtractNamedRight( |
264 mach_port_t task_port, | 280 mach_port_t task_port, |
265 mach_port_name_t named_right) { | 281 mach_port_name_t named_right) { |
266 mach_port_t extracted_right = MACH_PORT_NULL; | 282 mach_port_t extracted_right = MACH_PORT_NULL; |
267 mach_msg_type_name_t extracted_right_type; | 283 mach_msg_type_name_t extracted_right_type; |
268 kern_return_t kr = | 284 kern_return_t kr = |
269 mach_port_extract_right(task_port, named_right, MACH_MSG_TYPE_COPY_SEND, | 285 mach_port_extract_right(task_port, named_right, MACH_MSG_TYPE_COPY_SEND, |
270 &extracted_right, &extracted_right_type); | 286 &extracted_right, &extracted_right_type); |
271 if (kr != KERN_SUCCESS) { | 287 if (kr != KERN_SUCCESS) { |
272 LogError(ERROR_EXTRACT_SOURCE_RIGHT); | 288 LogError(ERROR_EXTRACT_SOURCE_RIGHT); |
(...skipping 25 matching lines...) Expand all Loading... |
298 void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess( | 314 void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess( |
299 base::ProcessId pid) { | 315 base::ProcessId pid) { |
300 base::AutoLock l(precursors_lock_); | 316 base::AutoLock l(precursors_lock_); |
301 auto it = precursors_.find(pid); | 317 auto it = precursors_.find(pid); |
302 if (it == precursors_.end()) | 318 if (it == precursors_.end()) |
303 return; | 319 return; |
304 | 320 |
305 // Whether this process is the destination process. | 321 // Whether this process is the destination process. |
306 bool to_self = pid == base::GetCurrentProcId(); | 322 bool to_self = pid == base::GetCurrentProcId(); |
307 | 323 |
| 324 if (!to_self) { |
| 325 if (!GetSenderWithProcessId(pid)) { |
| 326 // If there is no sender, then the destination process is no longer |
| 327 // running, or never existed to begin with. |
| 328 LogError(DESTINATION_NOT_FOUND); |
| 329 delete it->second; |
| 330 precursors_.erase(it); |
| 331 return; |
| 332 } |
| 333 } |
| 334 |
308 mach_port_t task_port = port_provider_->TaskForPid(pid); | 335 mach_port_t task_port = port_provider_->TaskForPid(pid); |
| 336 |
| 337 // It's possible that the destination process has not yet provided the |
| 338 // privileged process with its task port. |
309 if (!to_self && task_port == MACH_PORT_NULL) | 339 if (!to_self && task_port == MACH_PORT_NULL) |
310 return; | 340 return; |
311 | 341 |
312 while (!it->second->empty()) { | 342 while (!it->second->empty()) { |
313 auto precursor_it = it->second->begin(); | 343 auto precursor_it = it->second->begin(); |
314 if (to_self) | 344 if (to_self) { |
315 RoutePrecursorToSelf(*precursor_it); | 345 RoutePrecursorToSelf(*precursor_it); |
316 else | 346 } else { |
317 SendPrecursor(*precursor_it, task_port); | 347 if (!SendPrecursor(*precursor_it, task_port)) |
| 348 break; |
| 349 } |
318 it->second->erase(precursor_it); | 350 it->second->erase(precursor_it); |
319 } | 351 } |
320 | 352 |
321 delete it->second; | 353 delete it->second; |
322 precursors_.erase(it); | 354 precursors_.erase(it); |
323 } | 355 } |
324 | 356 |
325 void AttachmentBrokerPrivilegedMac::SendPrecursor( | 357 bool AttachmentBrokerPrivilegedMac::SendPrecursor( |
326 AttachmentPrecursor* precursor, | 358 AttachmentPrecursor* precursor, |
327 mach_port_t task_port) { | 359 mach_port_t task_port) { |
328 DCHECK(task_port); | 360 DCHECK(task_port); |
329 internal::MachPortAttachmentMac::WireFormat wire_format( | 361 internal::MachPortAttachmentMac::WireFormat wire_format( |
330 MACH_PORT_NULL, precursor->pid(), precursor->id()); | 362 MACH_PORT_NULL, precursor->pid(), precursor->id()); |
331 base::mac::ScopedMachSendRight port_to_insert = precursor->TakePort(); | 363 base::mac::ScopedMachSendRight port_to_insert = precursor->TakePort(); |
332 mach_port_name_t intermediate_port = MACH_PORT_NULL; | 364 mach_port_name_t intermediate_port = MACH_PORT_NULL; |
333 if (port_to_insert.get() != MACH_PORT_NULL) { | 365 if (port_to_insert.get() != MACH_PORT_NULL) { |
334 intermediate_port = CreateIntermediateMachPort( | 366 intermediate_port = CreateIntermediateMachPort( |
335 task_port, base::mac::ScopedMachSendRight(port_to_insert.release())); | 367 task_port, base::mac::ScopedMachSendRight(port_to_insert.release())); |
336 } | 368 } |
337 RouteWireFormatToAnother(CopyWireFormat(wire_format, intermediate_port)); | 369 return RouteWireFormatToAnother( |
| 370 CopyWireFormat(wire_format, intermediate_port)); |
338 } | 371 } |
339 | 372 |
340 void AttachmentBrokerPrivilegedMac::AddPrecursor( | 373 void AttachmentBrokerPrivilegedMac::AddPrecursor( |
341 base::ProcessId pid, | 374 base::ProcessId pid, |
342 base::mac::ScopedMachSendRight port, | 375 base::mac::ScopedMachSendRight port, |
343 const BrokerableAttachment::AttachmentId& id) { | 376 const BrokerableAttachment::AttachmentId& id) { |
344 base::AutoLock l(precursors_lock_); | 377 base::AutoLock l(precursors_lock_); |
345 auto it = precursors_.find(pid); | 378 auto it = precursors_.find(pid); |
346 if (it == precursors_.end()) | 379 if (it == precursors_.end()) |
347 precursors_[pid] = new ScopedVector<AttachmentPrecursor>; | 380 precursors_[pid] = new ScopedVector<AttachmentPrecursor>; |
348 | 381 |
349 precursors_[pid]->push_back(new AttachmentPrecursor( | 382 precursors_[pid]->push_back(new AttachmentPrecursor( |
350 pid, base::mac::ScopedMachSendRight(port.release()), id)); | 383 pid, base::mac::ScopedMachSendRight(port.release()), id)); |
351 } | 384 } |
352 | 385 |
353 void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess( | 386 void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess( |
354 base::ProcessId pid) { | 387 base::ProcessId pid) { |
355 base::AutoLock l(extractors_lock_); | 388 base::AutoLock l(extractors_lock_); |
356 auto it = extractors_.find(pid); | 389 auto it = extractors_.find(pid); |
357 if (it == extractors_.end()) | 390 if (it == extractors_.end()) |
358 return; | 391 return; |
359 | 392 |
| 393 if (!GetSenderWithProcessId(pid)) { |
| 394 // If there is no sender, then the source process is no longer running. |
| 395 LogError(ERROR_SOURCE_NOT_FOUND); |
| 396 delete it->second; |
| 397 extractors_.erase(it); |
| 398 return; |
| 399 } |
| 400 |
360 mach_port_t task_port = port_provider_->TaskForPid(pid); | 401 mach_port_t task_port = port_provider_->TaskForPid(pid); |
| 402 |
| 403 // It's possible that the source process has not yet provided the privileged |
| 404 // process with its task port. |
361 if (task_port == MACH_PORT_NULL) | 405 if (task_port == MACH_PORT_NULL) |
362 return; | 406 return; |
363 | 407 |
364 while (!it->second->empty()) { | 408 while (!it->second->empty()) { |
365 auto extractor_it = it->second->begin(); | 409 auto extractor_it = it->second->begin(); |
366 ProcessExtractor(*extractor_it, task_port); | 410 ProcessExtractor(*extractor_it, task_port); |
367 it->second->erase(extractor_it); | 411 it->second->erase(extractor_it); |
368 } | 412 } |
369 | 413 |
370 delete it->second; | 414 delete it->second; |
(...skipping 22 matching lines...) Expand all Loading... |
393 | 437 |
394 auto it = extractors_.find(source_pid); | 438 auto it = extractors_.find(source_pid); |
395 if (it == extractors_.end()) | 439 if (it == extractors_.end()) |
396 extractors_[source_pid] = new ScopedVector<AttachmentExtractor>; | 440 extractors_[source_pid] = new ScopedVector<AttachmentExtractor>; |
397 | 441 |
398 extractors_[source_pid]->push_back( | 442 extractors_[source_pid]->push_back( |
399 new AttachmentExtractor(source_pid, dest_pid, port, id)); | 443 new AttachmentExtractor(source_pid, dest_pid, port, id)); |
400 } | 444 } |
401 | 445 |
402 } // namespace IPC | 446 } // namespace IPC |
OLD | NEW |