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

Side by Side Diff: ipc/attachment_broker_privileged_mac.cc

Issue 1978353003: mac: Fix an attachment broker race condition. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@temp48_windows_ab
Patch Set: Created 4 years, 7 months 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
« no previous file with comments | « ipc/attachment_broker_privileged_mac.h ('k') | ipc/ipc_channel_posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stdint.h> 7 #include <stdint.h>
8 8
9 #include <tuple> 9 #include <tuple>
10 10
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 switch (attachment->GetBrokerableType()) { 47 switch (attachment->GetBrokerableType()) {
48 case BrokerableAttachment::MACH_PORT: { 48 case BrokerableAttachment::MACH_PORT: {
49 internal::MachPortAttachmentMac* mach_port_attachment = 49 internal::MachPortAttachmentMac* mach_port_attachment =
50 static_cast<internal::MachPortAttachmentMac*>(attachment.get()); 50 static_cast<internal::MachPortAttachmentMac*>(attachment.get());
51 MachPortWireFormat wire_format = 51 MachPortWireFormat wire_format =
52 mach_port_attachment->GetWireFormat(destination_process); 52 mach_port_attachment->GetWireFormat(destination_process);
53 AddPrecursor(wire_format.destination_process, 53 AddPrecursor(wire_format.destination_process,
54 base::mac::ScopedMachSendRight(wire_format.mach_port), 54 base::mac::ScopedMachSendRight(wire_format.mach_port),
55 wire_format.attachment_id); 55 wire_format.attachment_id);
56 mach_port_attachment->reset_mach_port_ownership(); 56 mach_port_attachment->reset_mach_port_ownership();
57 SendPrecursorsForProcess(wire_format.destination_process); 57 SendPrecursorsForProcess(wire_format.destination_process, true);
58 return true; 58 return true;
59 } 59 }
60 default: 60 default:
61 NOTREACHED(); 61 NOTREACHED();
62 return false; 62 return false;
63 } 63 }
64 return false; 64 return false;
65 } 65 }
66 66
67 void AttachmentBrokerPrivilegedMac::DeregisterCommunicationChannel( 67 void AttachmentBrokerPrivilegedMac::DeregisterCommunicationChannel(
(...skipping 19 matching lines...) Expand all
87 { 87 {
88 base::AutoLock l(extractors_lock_); 88 base::AutoLock l(extractors_lock_);
89 auto it = extractors_.find(pid); 89 auto it = extractors_.find(pid);
90 if (it != extractors_.end()) { 90 if (it != extractors_.end()) {
91 delete it->second; 91 delete it->second;
92 extractors_.erase(pid); 92 extractors_.erase(pid);
93 } 93 }
94 } 94 }
95 } 95 }
96 96
97 void AttachmentBrokerPrivilegedMac::ReceivedPeerPid(base::ProcessId peer_pid) {
98 ProcessExtractorsForProcess(peer_pid, false);
99 SendPrecursorsForProcess(peer_pid, false);
100 }
101
97 bool AttachmentBrokerPrivilegedMac::OnMessageReceived(const Message& msg) { 102 bool AttachmentBrokerPrivilegedMac::OnMessageReceived(const Message& msg) {
98 bool handled = true; 103 bool handled = true;
99 switch (msg.type()) { 104 switch (msg.type()) {
100 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateMachPort, 105 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateMachPort,
101 OnDuplicateMachPort(msg)) 106 OnDuplicateMachPort(msg))
102 IPC_MESSAGE_UNHANDLED(handled = false) 107 IPC_MESSAGE_UNHANDLED(handled = false)
103 } 108 }
104 return handled; 109 return handled;
105 } 110 }
106 111
107 void AttachmentBrokerPrivilegedMac::OnReceivedTaskPort( 112 void AttachmentBrokerPrivilegedMac::OnReceivedTaskPort(
108 base::ProcessHandle process) { 113 base::ProcessHandle process) {
109 SendPrecursorsForProcess(process); 114 SendPrecursorsForProcess(process, true);
110 } 115 }
111 116
112 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::AttachmentPrecursor( 117 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::AttachmentPrecursor(
113 const base::ProcessId& pid, 118 const base::ProcessId& pid,
114 base::mac::ScopedMachSendRight port, 119 base::mac::ScopedMachSendRight port,
115 const BrokerableAttachment::AttachmentId& id) 120 const BrokerableAttachment::AttachmentId& id)
116 : pid_(pid), port_(port.release()), id_(id) {} 121 : pid_(pid), port_(port.release()), id_(id) {}
117 122
118 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::~AttachmentPrecursor() {} 123 AttachmentBrokerPrivilegedMac::AttachmentPrecursor::~AttachmentPrecursor() {}
119 124
(...skipping 25 matching lines...) Expand all
145 IPC::internal::MachPortAttachmentMac::WireFormat wire_format = 150 IPC::internal::MachPortAttachmentMac::WireFormat wire_format =
146 std::get<0>(param); 151 std::get<0>(param);
147 152
148 if (wire_format.destination_process == base::kNullProcessId) { 153 if (wire_format.destination_process == base::kNullProcessId) {
149 LogError(NO_DESTINATION); 154 LogError(NO_DESTINATION);
150 return; 155 return;
151 } 156 }
152 157
153 AddExtractor(message.get_sender_pid(), wire_format.destination_process, 158 AddExtractor(message.get_sender_pid(), wire_format.destination_process,
154 wire_format.mach_port, wire_format.attachment_id); 159 wire_format.mach_port, wire_format.attachment_id);
155 ProcessExtractorsForProcess(message.get_sender_pid()); 160 ProcessExtractorsForProcess(message.get_sender_pid(), true);
156 } 161 }
157 162
158 void AttachmentBrokerPrivilegedMac::RoutePrecursorToSelf( 163 void AttachmentBrokerPrivilegedMac::RoutePrecursorToSelf(
159 AttachmentPrecursor* precursor) { 164 AttachmentPrecursor* precursor) {
160 DCHECK_EQ(base::Process::Current().Pid(), precursor->pid()); 165 DCHECK_EQ(base::Process::Current().Pid(), precursor->pid());
161 166
162 // Intentionally leak the port, since the attachment takes ownership. 167 // Intentionally leak the port, since the attachment takes ownership.
163 internal::MachPortAttachmentMac::WireFormat wire_format( 168 internal::MachPortAttachmentMac::WireFormat wire_format(
164 precursor->TakePort().release(), precursor->pid(), precursor->id()); 169 precursor->TakePort().release(), precursor->pid(), precursor->id());
165 scoped_refptr<BrokerableAttachment> attachment( 170 scoped_refptr<BrokerableAttachment> attachment(
166 new internal::MachPortAttachmentMac(wire_format)); 171 new internal::MachPortAttachmentMac(wire_format));
167 HandleReceivedAttachment(attachment); 172 HandleReceivedAttachment(attachment);
168 } 173 }
169 174
170 bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother( 175 bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother(
171 const MachPortWireFormat& wire_format) { 176 const MachPortWireFormat& wire_format) {
172 DCHECK_NE(wire_format.destination_process, base::Process::Current().Pid()); 177 DCHECK_NE(wire_format.destination_process, base::Process::Current().Pid());
173 178
174 // Another process is the destination. 179 // Another process is the destination.
175 base::ProcessId dest = wire_format.destination_process; 180 base::ProcessId dest = wire_format.destination_process;
176 base::AutoLock auto_lock(*get_lock()); 181 base::AutoLock auto_lock(*get_lock());
177 AttachmentBrokerPrivileged::EndpointRunnerPair pair = 182 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
178 GetSenderWithProcessId(dest); 183 GetSenderWithProcessId(dest);
179 if (!pair.first) { 184 if (!pair.first) {
180 // Assuming that this message was not sent from a malicious process, the 185 // The extractor was successfully processed, which implies that the
181 // channel endpoint that would have received this message will block 186 // communication channel was established. This implies that the
182 // forever. 187 // communication was taken down in the interim.
183 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: " 188 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: "
184 << dest; 189 << dest;
185 LogError(DESTINATION_NOT_FOUND); 190 LogError(DESTINATION_NOT_FOUND);
186 return false; 191 return false;
187 } 192 }
188 193
189 LogError(DESTINATION_FOUND); 194 LogError(DESTINATION_FOUND);
190 SendMessageToEndpoint( 195 SendMessageToEndpoint(
191 pair, new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format)); 196 pair, new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format));
192 return true; 197 return true;
(...skipping 23 matching lines...) Expand all
216 221
217 AttachmentBrokerPrivilegedMac::MachPortWireFormat 222 AttachmentBrokerPrivilegedMac::MachPortWireFormat
218 AttachmentBrokerPrivilegedMac::CopyWireFormat( 223 AttachmentBrokerPrivilegedMac::CopyWireFormat(
219 const MachPortWireFormat& wire_format, 224 const MachPortWireFormat& wire_format,
220 uint32_t mach_port) { 225 uint32_t mach_port) {
221 return MachPortWireFormat(mach_port, wire_format.destination_process, 226 return MachPortWireFormat(mach_port, wire_format.destination_process,
222 wire_format.attachment_id); 227 wire_format.attachment_id);
223 } 228 }
224 229
225 void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess( 230 void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess(
226 base::ProcessId pid) { 231 base::ProcessId pid,
232 bool store_on_failure) {
227 base::AutoLock l(precursors_lock_); 233 base::AutoLock l(precursors_lock_);
228 auto it = precursors_.find(pid); 234 auto it = precursors_.find(pid);
229 if (it == precursors_.end()) 235 if (it == precursors_.end())
230 return; 236 return;
231 237
232 // Whether this process is the destination process. 238 // Whether this process is the destination process.
233 bool to_self = pid == base::GetCurrentProcId(); 239 bool to_self = pid == base::GetCurrentProcId();
234 240
235 if (!to_self) { 241 if (!to_self) {
236 base::AutoLock auto_lock(*get_lock()); 242 base::AutoLock auto_lock(*get_lock());
237 AttachmentBrokerPrivileged::EndpointRunnerPair pair = 243 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
238 GetSenderWithProcessId(pid); 244 GetSenderWithProcessId(pid);
239 if (!pair.first) { 245 if (!pair.first) {
240 // If there is no sender, then the destination process is no longer 246 if (store_on_failure) {
241 // running, or never existed to begin with. 247 // Try again later.
242 LogError(DESTINATION_NOT_FOUND); 248 LogError(DELAYED);
243 delete it->second; 249 } else {
244 precursors_.erase(it); 250 // If there is no sender, then permanently fail.
251 LogError(DESTINATION_NOT_FOUND);
252 delete it->second;
253 precursors_.erase(it);
254 }
245 return; 255 return;
246 } 256 }
247 } 257 }
248 258
249 mach_port_t task_port = port_provider_->TaskForPid(pid); 259 mach_port_t task_port = port_provider_->TaskForPid(pid);
250 260
251 // It's possible that the destination process has not yet provided the 261 // It's possible that the destination process has not yet provided the
252 // privileged process with its task port. 262 // privileged process with its task port.
253 if (!to_self && task_port == MACH_PORT_NULL) 263 if (!to_self && task_port == MACH_PORT_NULL)
254 return; 264 return;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 base::AutoLock l(precursors_lock_); 321 base::AutoLock l(precursors_lock_);
312 auto it = precursors_.find(pid); 322 auto it = precursors_.find(pid);
313 if (it == precursors_.end()) 323 if (it == precursors_.end())
314 precursors_[pid] = new ScopedVector<AttachmentPrecursor>; 324 precursors_[pid] = new ScopedVector<AttachmentPrecursor>;
315 325
316 precursors_[pid]->push_back(new AttachmentPrecursor( 326 precursors_[pid]->push_back(new AttachmentPrecursor(
317 pid, base::mac::ScopedMachSendRight(port.release()), id)); 327 pid, base::mac::ScopedMachSendRight(port.release()), id));
318 } 328 }
319 329
320 void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess( 330 void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess(
321 base::ProcessId pid) { 331 base::ProcessId pid,
332 bool store_on_failure) {
322 base::AutoLock l(extractors_lock_); 333 base::AutoLock l(extractors_lock_);
323 auto it = extractors_.find(pid); 334 auto it = extractors_.find(pid);
324 if (it == extractors_.end()) 335 if (it == extractors_.end())
325 return; 336 return;
326 337
327 { 338 {
328 base::AutoLock auto_lock(*get_lock()); 339 base::AutoLock auto_lock(*get_lock());
329 AttachmentBrokerPrivileged::EndpointRunnerPair pair = 340 AttachmentBrokerPrivileged::EndpointRunnerPair pair =
330 GetSenderWithProcessId(pid); 341 GetSenderWithProcessId(pid);
331 if (!pair.first) { 342 if (!pair.first) {
332 // If there is no sender, then the source process is no longer running. 343 if (store_on_failure) {
333 LogError(ERROR_SOURCE_NOT_FOUND); 344 // If there is no sender, then the communication channel with the source
334 delete it->second; 345 // process has not yet been established. Try again later.
335 extractors_.erase(it); 346 LogError(DELAYED);
347 } else {
348 // There is no sender. Permanently fail.
349 LogError(ERROR_SOURCE_NOT_FOUND);
350 delete it->second;
351 extractors_.erase(it);
352 }
336 return; 353 return;
337 } 354 }
338 } 355 }
339 356
340 mach_port_t task_port = port_provider_->TaskForPid(pid); 357 mach_port_t task_port = port_provider_->TaskForPid(pid);
341 358
342 // It's possible that the source process has not yet provided the privileged 359 // It's possible that the source process has not yet provided the privileged
343 // process with its task port. 360 // process with its task port.
344 if (task_port == MACH_PORT_NULL) 361 if (task_port == MACH_PORT_NULL)
345 return; 362 return;
(...skipping 10 matching lines...) Expand all
356 373
357 void AttachmentBrokerPrivilegedMac::ProcessExtractor( 374 void AttachmentBrokerPrivilegedMac::ProcessExtractor(
358 AttachmentExtractor* extractor, 375 AttachmentExtractor* extractor,
359 mach_port_t task_port) { 376 mach_port_t task_port) {
360 DCHECK(task_port); 377 DCHECK(task_port);
361 base::mac::ScopedMachSendRight send_right = 378 base::mac::ScopedMachSendRight send_right =
362 ExtractNamedRight(task_port, extractor->port()); 379 ExtractNamedRight(task_port, extractor->port());
363 AddPrecursor(extractor->dest_pid(), 380 AddPrecursor(extractor->dest_pid(),
364 base::mac::ScopedMachSendRight(send_right.release()), 381 base::mac::ScopedMachSendRight(send_right.release()),
365 extractor->id()); 382 extractor->id());
366 SendPrecursorsForProcess(extractor->dest_pid()); 383 SendPrecursorsForProcess(extractor->dest_pid(), true);
367 } 384 }
368 385
369 void AttachmentBrokerPrivilegedMac::AddExtractor( 386 void AttachmentBrokerPrivilegedMac::AddExtractor(
370 base::ProcessId source_pid, 387 base::ProcessId source_pid,
371 base::ProcessId dest_pid, 388 base::ProcessId dest_pid,
372 mach_port_name_t port, 389 mach_port_name_t port,
373 const BrokerableAttachment::AttachmentId& id) { 390 const BrokerableAttachment::AttachmentId& id) {
374 base::AutoLock l(extractors_lock_); 391 base::AutoLock l(extractors_lock_);
375 DCHECK_NE(base::GetCurrentProcId(), source_pid); 392 DCHECK_NE(base::GetCurrentProcId(), source_pid);
376 393
377 auto it = extractors_.find(source_pid); 394 auto it = extractors_.find(source_pid);
378 if (it == extractors_.end()) 395 if (it == extractors_.end())
379 extractors_[source_pid] = new ScopedVector<AttachmentExtractor>; 396 extractors_[source_pid] = new ScopedVector<AttachmentExtractor>;
380 397
381 extractors_[source_pid]->push_back( 398 extractors_[source_pid]->push_back(
382 new AttachmentExtractor(source_pid, dest_pid, port, id)); 399 new AttachmentExtractor(source_pid, dest_pid, port, id));
383 } 400 }
384 401
385 } // namespace IPC 402 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/attachment_broker_privileged_mac.h ('k') | ipc/ipc_channel_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698