OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/mach_broker_mac.h" | 5 #include "content/browser/mach_broker_mac.h" |
6 | 6 |
7 #include <bsm/libbsm.h> | 7 #include <bsm/libbsm.h> |
8 #include <servers/bootstrap.h> | 8 #include <servers/bootstrap.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/mac/foundation_util.h" | 14 #include "base/mac/foundation_util.h" |
15 #include "base/mac/mach_logging.h" | 15 #include "base/mac/mach_logging.h" |
16 #include "base/mac/scoped_mach_port.h" | 16 #include "base/mac/scoped_mach_port.h" |
17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
20 #include "base/threading/platform_thread.h" | 20 #include "base/threading/platform_thread.h" |
21 #include "content/browser/renderer_host/render_process_host_impl.h" | 21 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 22 #include "content/common/mac/io_surface_manager.h" |
22 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
23 #include "content/public/browser/child_process_data.h" | 24 #include "content/public/browser/child_process_data.h" |
24 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
25 #include "content/public/browser/notification_types.h" | 26 #include "content/public/browser/notification_types.h" |
26 #include "content/public/common/content_switches.h" | 27 #include "content/public/common/content_switches.h" |
27 | 28 |
28 namespace content { | 29 namespace content { |
29 | |
30 namespace { | 30 namespace { |
31 | 31 |
| 32 // Message IDs. |
| 33 // Note: we currently use __LINE__ to give unique IDs to messages. |
| 34 // They're unique since all messages are defined in this file. |
| 35 #define MACH_MESSAGE_ID() __LINE__ |
| 36 |
| 37 #define MACH_MESSAGE_STRUCT_HEADER() \ |
| 38 mach_msg_header_t header; \ |
| 39 mach_msg_body_t body; |
| 40 |
| 41 #define MACH_HOST_MESSAGE_STRUCT_HEADER() \ |
| 42 enum { ID = MACH_MESSAGE_ID() }; \ |
| 43 mach_msg_header_t header; \ |
| 44 mach_msg_body_t body; |
| 45 |
| 46 struct MachBroker_ChildMsg { |
| 47 MACH_HOST_MESSAGE_STRUCT_HEADER() |
| 48 |
| 49 mach_msg_port_descriptor_t child_task_port; |
| 50 }; |
| 51 |
| 52 // Complement to the ChildMsg, this is used in the parent for receiving |
| 53 // a message. Contains a message trailer with audit information. |
| 54 struct MachBroker_ChildRecvMsg : public MachBroker_ChildMsg { |
| 55 mach_msg_audit_trailer_t trailer; |
| 56 }; |
| 57 |
32 // Mach message structure used in the child as a sending message. | 58 // Mach message structure used in the child as a sending message. |
33 struct MachBroker_ChildSendMsg { | 59 struct MachBroker_RegisterIOSurfaceMsg { |
34 mach_msg_header_t header; | 60 MACH_HOST_MESSAGE_STRUCT_HEADER() |
35 mach_msg_body_t body; | 61 |
36 mach_msg_port_descriptor_t child_task_port; | 62 mach_msg_port_descriptor_t io_surface_port; |
37 }; | 63 int io_surface_id; |
38 | 64 int client_id; |
39 // Complement to the ChildSendMsg, this is used in the parent for receiving | 65 }; |
40 // a message. Contains a message trailer with audit information. | 66 |
41 struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg { | 67 // Complement to the RegisterIOSurfaceMsg, this is used in the parent for |
42 mach_msg_audit_trailer_t trailer; | 68 // receiving a message. Contains a message trailer with audit information. |
| 69 struct MachBroker_RegisterIOSurfaceRecvMsg |
| 70 : public MachBroker_RegisterIOSurfaceMsg { |
| 71 mach_msg_audit_trailer_t trailer; |
| 72 }; |
| 73 |
| 74 // Mach message structure used in the parent as a sending message. |
| 75 struct MachBroker_RegisterIOSurfaceReplyMsg { |
| 76 MACH_HOST_MESSAGE_STRUCT_HEADER() |
| 77 |
| 78 boolean_t result; |
| 79 }; |
| 80 |
| 81 // Complement to the RegisterIOSurfaceReplyMsg, this is used in the child |
| 82 // for receiving a message. Contains a message trailer. |
| 83 struct MachBroker_RegisterIOSurfaceReplyRecvMsg |
| 84 : public MachBroker_RegisterIOSurfaceReplyMsg { |
| 85 mach_msg_trailer_t trailer; |
| 86 }; |
| 87 |
| 88 // Mach message structure used in the child as a sending message. |
| 89 struct MachBroker_UnregisterIOSurfaceMsg { |
| 90 MACH_HOST_MESSAGE_STRUCT_HEADER() |
| 91 |
| 92 int io_surface_id; |
| 93 int client_id; |
| 94 }; |
| 95 |
| 96 // Complement to the UnregisterIOSurfaceMsg, this is used in the parent for |
| 97 // receiving a message. Contains a message trailer with audit information. |
| 98 struct MachBroker_UnregisterIOSurfaceRecvMsg |
| 99 : public MachBroker_UnregisterIOSurfaceMsg { |
| 100 mach_msg_audit_trailer_t trailer; |
| 101 }; |
| 102 |
| 103 // Mach message structure used in the child as a sending message. |
| 104 struct MachBroker_AcquireIOSurfaceMsg { |
| 105 MACH_HOST_MESSAGE_STRUCT_HEADER() |
| 106 |
| 107 int io_surface_id; |
| 108 }; |
| 109 |
| 110 // Complement to the AcquireIOSurfaceMsg, this is used in the parent for |
| 111 // receiving a message. Contains a message trailer with audit information. |
| 112 struct MachBroker_AcquireIOSurfaceRecvMsg |
| 113 : public MachBroker_AcquireIOSurfaceMsg { |
| 114 mach_msg_audit_trailer_t trailer; |
| 115 }; |
| 116 |
| 117 // Mach message structure used in the parent as a sending message. |
| 118 struct MachBroker_AcquireIOSurfaceReplyMsg { |
| 119 MACH_MESSAGE_STRUCT_HEADER() |
| 120 |
| 121 mach_msg_port_descriptor_t io_surface_port; |
| 122 }; |
| 123 |
| 124 // Complement to the AcquireIOSurfaceReplyMsg, this is used in the child for |
| 125 // receiving a message. Contains a message trailer. |
| 126 struct MachBroker_AcquireIOSurfaceReplyRecvMsg |
| 127 : public MachBroker_AcquireIOSurfaceReplyMsg { |
| 128 mach_msg_trailer_t trailer; |
| 129 }; |
| 130 |
| 131 class IOSurfaceManagerImpl : public IOSurfaceManager { |
| 132 public: |
| 133 IOSurfaceManagerImpl(mach_port_t send_port, mach_port_t receive_port) |
| 134 : send_port_(send_port), receive_port_(receive_port) {} |
| 135 |
| 136 // Overridden from IOSurfaceManager: |
| 137 bool RegisterIOSurface(int io_surface_id, |
| 138 int client_id, |
| 139 IOSurfaceRef io_surface) override { |
| 140 base::AutoLock lock(lock_); |
| 141 |
| 142 // Deallocate the right after sending a copy to the parent. |
| 143 base::mac::ScopedMachSendRight scoped_io_surface_right( |
| 144 IOSurfaceCreateMachPort(io_surface)); |
| 145 |
| 146 union { |
| 147 MachBroker_RegisterIOSurfaceMsg request; |
| 148 MachBroker_RegisterIOSurfaceReplyRecvMsg reply; |
| 149 } msg; |
| 150 bzero(&msg, sizeof(msg)); |
| 151 msg.request.header.msgh_bits = |
| 152 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) | |
| 153 MACH_MSGH_BITS_COMPLEX; |
| 154 msg.request.header.msgh_remote_port = send_port_; |
| 155 msg.request.header.msgh_local_port = receive_port_; |
| 156 msg.request.header.msgh_size = sizeof(msg.request); |
| 157 msg.request.header.msgh_id = MachBroker_RegisterIOSurfaceMsg::ID; |
| 158 msg.request.body.msgh_descriptor_count = 1; |
| 159 msg.request.io_surface_port.name = scoped_io_surface_right; |
| 160 msg.request.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND; |
| 161 msg.request.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR; |
| 162 msg.request.io_surface_id = io_surface_id; |
| 163 msg.request.client_id = client_id; |
| 164 |
| 165 kern_return_t kr = |
| 166 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG, |
| 167 sizeof(msg.request), sizeof(msg.reply), receive_port_, |
| 168 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); |
| 169 if (kr != KERN_SUCCESS) { |
| 170 MACH_LOG(ERROR, kr) << "mach_msg"; |
| 171 return false; |
| 172 } |
| 173 |
| 174 return msg.reply.result; |
| 175 } |
| 176 void UnregisterIOSurface(int io_surface_id, int client_id) override { |
| 177 base::AutoLock lock(lock_); |
| 178 |
| 179 MachBroker_UnregisterIOSurfaceMsg msg; |
| 180 bzero(&msg, sizeof(msg)); |
| 181 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); |
| 182 msg.header.msgh_remote_port = send_port_; |
| 183 msg.header.msgh_local_port = MACH_PORT_NULL; |
| 184 msg.header.msgh_size = sizeof(msg); |
| 185 msg.header.msgh_id = MachBroker_UnregisterIOSurfaceMsg::ID; |
| 186 msg.io_surface_id = io_surface_id; |
| 187 msg.client_id = client_id; |
| 188 |
| 189 kern_return_t kr = |
| 190 mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0, |
| 191 MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); |
| 192 if (kr != KERN_SUCCESS) { |
| 193 MACH_LOG(ERROR, kr) << "mach_msg"; |
| 194 } |
| 195 } |
| 196 IOSurfaceRef AcquireIOSurface(int io_surface_id) override { |
| 197 base::AutoLock lock(lock_); |
| 198 |
| 199 union { |
| 200 MachBroker_AcquireIOSurfaceMsg request; |
| 201 MachBroker_AcquireIOSurfaceReplyRecvMsg reply; |
| 202 } msg; |
| 203 bzero(&msg, sizeof(msg)); |
| 204 msg.request.header.msgh_bits = |
| 205 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); |
| 206 msg.request.header.msgh_remote_port = send_port_; |
| 207 msg.request.header.msgh_local_port = receive_port_; |
| 208 msg.request.header.msgh_size = sizeof(msg.request); |
| 209 msg.request.header.msgh_id = MachBroker_AcquireIOSurfaceMsg::ID; |
| 210 msg.request.io_surface_id = io_surface_id; |
| 211 |
| 212 kern_return_t kr = |
| 213 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG, |
| 214 sizeof(msg.request), sizeof(msg.reply), receive_port_, |
| 215 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); |
| 216 if (kr != KERN_SUCCESS) { |
| 217 MACH_LOG(ERROR, kr) << "mach_msg"; |
| 218 return nullptr; |
| 219 } |
| 220 |
| 221 return IOSurfaceLookupFromMachPort(msg.reply.io_surface_port.name); |
| 222 } |
| 223 |
| 224 private: |
| 225 base::mac::ScopedMachSendRight send_port_; |
| 226 base::mac::ScopedMachSendRight receive_port_; |
| 227 base::Lock lock_; |
| 228 |
| 229 DISALLOW_COPY_AND_ASSIGN(IOSurfaceManagerImpl); |
43 }; | 230 }; |
44 | 231 |
45 } // namespace | 232 } // namespace |
46 | 233 |
47 class MachListenerThreadDelegate : public base::PlatformThread::Delegate { | 234 class MachListenerThreadDelegate : public base::PlatformThread::Delegate { |
48 public: | 235 public: |
49 explicit MachListenerThreadDelegate(MachBroker* broker) | 236 explicit MachListenerThreadDelegate(MachBroker* broker) |
50 : broker_(broker), | 237 : broker_(broker), |
51 server_port_(MACH_PORT_NULL) { | 238 server_port_(MACH_PORT_NULL) { |
52 DCHECK(broker_); | 239 DCHECK(broker_); |
(...skipping 26 matching lines...) Expand all Loading... |
79 // is deprecated, this has to be wraped in an ObjC interface. | 266 // is deprecated, this has to be wraped in an ObjC interface. |
80 NSPort* ns_port = [NSMachPort portWithMachPort:port | 267 NSPort* ns_port = [NSMachPort portWithMachPort:port |
81 options:NSMachPortDeallocateNone]; | 268 options:NSMachPortDeallocateNone]; |
82 NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName()); | 269 NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName()); |
83 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port | 270 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port |
84 name:name]; | 271 name:name]; |
85 } | 272 } |
86 | 273 |
87 // Implement |PlatformThread::Delegate|. | 274 // Implement |PlatformThread::Delegate|. |
88 void ThreadMain() override { | 275 void ThreadMain() override { |
89 MachBroker_ParentRecvMsg msg; | 276 union { |
| 277 mach_msg_header_t header; |
| 278 MachBroker_ChildRecvMsg child; |
| 279 MachBroker_RegisterIOSurfaceRecvMsg register_io_surface; |
| 280 MachBroker_UnregisterIOSurfaceRecvMsg unregister_io_surface; |
| 281 MachBroker_AcquireIOSurfaceRecvMsg acquire_io_surface; |
| 282 } msg; |
90 bzero(&msg, sizeof(msg)); | 283 bzero(&msg, sizeof(msg)); |
91 msg.header.msgh_size = sizeof(msg); | 284 msg.header.msgh_size = sizeof(msg); |
92 msg.header.msgh_local_port = server_port_.get(); | 285 msg.header.msgh_local_port = server_port_.get(); |
93 | 286 |
94 const mach_msg_option_t options = MACH_RCV_MSG | | 287 const mach_msg_option_t options = MACH_RCV_MSG | |
95 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | | 288 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | |
96 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); | 289 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); |
97 | 290 |
98 kern_return_t kr; | 291 kern_return_t kr; |
99 while ((kr = mach_msg(&msg.header, | 292 while ((kr = mach_msg(&msg.header, |
100 options, | 293 options, |
101 0, | 294 0, |
102 sizeof(msg), | 295 sizeof(msg), |
103 server_port_, | 296 server_port_, |
104 MACH_MSG_TIMEOUT_NONE, | 297 MACH_MSG_TIMEOUT_NONE, |
105 MACH_PORT_NULL)) == KERN_SUCCESS) { | 298 MACH_PORT_NULL)) == KERN_SUCCESS) { |
106 // Use the kernel audit information to make sure this message is from | 299 // Use the kernel audit information to make sure this message is from |
107 // a task that this process spawned. The kernel audit token contains the | 300 // a task that this process spawned. The kernel audit token contains |
108 // unspoofable pid of the task that sent the message. | 301 // the unspoofable pid of the task that sent the message. |
109 // | 302 mach_msg_audit_trailer_t* trailer = |
| 303 reinterpret_cast<mach_msg_audit_trailer_t*>( |
| 304 reinterpret_cast<vm_address_t>(&msg.header) + |
| 305 round_msg(msg.header.msgh_size)); |
110 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). | 306 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). |
111 pid_t child_pid; | 307 pid_t child_pid; |
112 audit_token_to_au32(msg.trailer.msgh_audit, | 308 audit_token_to_au32(trailer->msgh_audit, NULL, NULL, NULL, NULL, NULL, |
113 NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); | 309 &child_pid, NULL, NULL); |
114 | 310 |
115 mach_port_t child_task_port = msg.child_task_port.name; | 311 // Take the lock. |
| 312 base::AutoLock lock(broker_->GetLock()); |
116 | 313 |
117 // Take the lock and update the broker information. | 314 switch (msg.header.msgh_id) { |
118 base::AutoLock lock(broker_->GetLock()); | 315 case MachBroker_ChildMsg::ID: { |
119 broker_->FinalizePid(child_pid, child_task_port); | 316 mach_port_t child_task_port = msg.child.child_task_port.name; |
| 317 |
| 318 // Update the broker information. |
| 319 broker_->FinalizePid(child_pid, child_task_port); |
| 320 } break; |
| 321 case MachBroker_RegisterIOSurfaceMsg::ID: { |
| 322 mach_port_t io_surface_port = |
| 323 msg.register_io_surface.io_surface_port.name; |
| 324 int io_surface_id = msg.register_io_surface.io_surface_id; |
| 325 int client_id = msg.register_io_surface.client_id; |
| 326 |
| 327 bool result = broker_->RegisterIOSurface(child_pid, io_surface_id, |
| 328 client_id, io_surface_port); |
| 329 |
| 330 MachBroker_RegisterIOSurfaceReplyMsg reply; |
| 331 bzero(&reply, sizeof(reply)); |
| 332 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits); |
| 333 reply.header.msgh_remote_port = msg.header.msgh_remote_port; |
| 334 reply.header.msgh_size = sizeof(reply); |
| 335 reply.result = result; |
| 336 kern_return_t kr = mach_msg( |
| 337 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), |
| 338 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); |
| 339 if (kr != KERN_SUCCESS) { |
| 340 MACH_LOG(ERROR, kr) << "mach_msg"; |
| 341 } |
| 342 |
| 343 } break; |
| 344 case MachBroker_UnregisterIOSurfaceMsg::ID: { |
| 345 int io_surface_id = msg.unregister_io_surface.io_surface_id; |
| 346 int client_id = msg.unregister_io_surface.client_id; |
| 347 |
| 348 broker_->UnregisterIOSurface(child_pid, io_surface_id, client_id); |
| 349 } break; |
| 350 case MachBroker_AcquireIOSurfaceMsg::ID: { |
| 351 int io_surface_id = msg.acquire_io_surface.io_surface_id; |
| 352 |
| 353 mach_port_t io_surface_port = |
| 354 broker_->AcquireIOSurface(child_pid, io_surface_id); |
| 355 |
| 356 MachBroker_AcquireIOSurfaceReplyMsg reply; |
| 357 bzero(&reply, sizeof(reply)); |
| 358 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits) | |
| 359 MACH_MSGH_BITS_COMPLEX; |
| 360 reply.header.msgh_remote_port = msg.header.msgh_remote_port; |
| 361 reply.header.msgh_size = sizeof(reply); |
| 362 reply.body.msgh_descriptor_count = 1; |
| 363 reply.io_surface_port.name = io_surface_port; |
| 364 reply.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND; |
| 365 reply.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR; |
| 366 kern_return_t kr = mach_msg( |
| 367 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), |
| 368 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); |
| 369 if (kr != KERN_SUCCESS) { |
| 370 MACH_LOG(ERROR, kr) << "mach_msg"; |
| 371 } |
| 372 } break; |
| 373 } |
120 } | 374 } |
121 | 375 |
122 MACH_LOG(ERROR, kr) << "mach_msg"; | 376 MACH_LOG(ERROR, kr) << "mach_msg"; |
123 } | 377 } |
124 | 378 |
125 private: | 379 private: |
126 // The MachBroker to use when new child task rights are received. Can be | 380 // The MachBroker to use when new child task rights are received. Can be |
127 // NULL. | 381 // NULL. |
128 MachBroker* broker_; // weak | 382 MachBroker* broker_; // weak |
129 | 383 |
130 base::mac::ScopedMachReceiveRight server_port_; | 384 base::mac::ScopedMachReceiveRight server_port_; |
131 | 385 |
132 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate); | 386 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate); |
133 }; | 387 }; |
134 | 388 |
135 bool MachBroker::ChildSendTaskPortToParent() { | 389 MachBroker::MachPortSet::MachPortSet() |
| 390 : is_gpu_process(false), task_port(MACH_PORT_NULL) { |
| 391 } |
| 392 |
| 393 MachBroker::MachPortSet::MachPortSet(bool is_gpu_process) |
| 394 : is_gpu_process(is_gpu_process), task_port(MACH_PORT_NULL) { |
| 395 } |
| 396 |
| 397 MachBroker::MachPortSet::~MachPortSet() { |
| 398 } |
| 399 |
| 400 // static |
| 401 bool MachBroker::InitChildProcess() { |
136 // Look up the named MachBroker port that's been registered with the | 402 // Look up the named MachBroker port that's been registered with the |
137 // bootstrap server. | 403 // bootstrap server. |
138 mach_port_t parent_port; | 404 mach_port_t parent_port; |
139 kern_return_t kr = bootstrap_look_up(bootstrap_port, | 405 kern_return_t kr = bootstrap_look_up(bootstrap_port, |
140 const_cast<char*>(GetMachPortName().c_str()), &parent_port); | 406 const_cast<char*>(GetMachPortName().c_str()), &parent_port); |
141 if (kr != KERN_SUCCESS) { | 407 if (kr != KERN_SUCCESS) { |
142 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; | 408 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; |
143 return false; | 409 return false; |
144 } | 410 } |
145 base::mac::ScopedMachSendRight scoped_right(parent_port); | 411 base::mac::ScopedMachSendRight scoped_parent_right(parent_port); |
| 412 |
| 413 mach_port_t child_port; |
| 414 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, |
| 415 &child_port); |
| 416 if (kr != KERN_SUCCESS) { |
| 417 MACH_LOG(ERROR, kr) << "mach_port_allocate"; |
| 418 return false; |
| 419 } |
| 420 base::mac::ScopedMachSendRight scoped_child_right(child_port); |
146 | 421 |
147 // Create the check in message. This will copy a send right on this process' | 422 // Create the check in message. This will copy a send right on this process' |
148 // (the child's) task port and send it to the parent. | 423 // (the child's) task port and send it to the parent. |
149 MachBroker_ChildSendMsg msg; | 424 MachBroker_ChildMsg msg; |
150 bzero(&msg, sizeof(msg)); | 425 bzero(&msg, sizeof(msg)); |
151 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | | 426 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | |
152 MACH_MSGH_BITS_COMPLEX; | 427 MACH_MSGH_BITS_COMPLEX; |
153 msg.header.msgh_remote_port = parent_port; | 428 msg.header.msgh_remote_port = parent_port; |
154 msg.header.msgh_size = sizeof(msg); | 429 msg.header.msgh_size = sizeof(msg); |
| 430 msg.header.msgh_id = MachBroker_ChildMsg::ID; |
155 msg.body.msgh_descriptor_count = 1; | 431 msg.body.msgh_descriptor_count = 1; |
156 msg.child_task_port.name = mach_task_self(); | 432 msg.child_task_port.name = mach_task_self(); |
157 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; | 433 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; |
158 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; | 434 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; |
159 | 435 |
160 kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), | 436 kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), |
161 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 437 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); |
162 if (kr != KERN_SUCCESS) { | 438 if (kr != KERN_SUCCESS) { |
163 MACH_LOG(ERROR, kr) << "mach_msg"; | 439 MACH_LOG(ERROR, kr) << "mach_msg"; |
164 return false; | 440 return false; |
165 } | 441 } |
166 | 442 |
| 443 IOSurfaceManager::InitInstance(new IOSurfaceManagerImpl( |
| 444 scoped_parent_right.release(), scoped_child_right.release())); |
| 445 |
167 return true; | 446 return true; |
168 } | 447 } |
169 | 448 |
170 MachBroker* MachBroker::GetInstance() { | 449 MachBroker* MachBroker::GetInstance() { |
171 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get(); | 450 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get(); |
172 } | 451 } |
173 | 452 |
174 base::Lock& MachBroker::GetLock() { | 453 base::Lock& MachBroker::GetLock() { |
175 return lock_; | 454 return lock_; |
176 } | 455 } |
(...skipping 12 matching lines...) Expand all Loading... |
189 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); | 468 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); |
190 if (thread->Init()) { | 469 if (thread->Init()) { |
191 base::PlatformThread::CreateNonJoinable(0, thread); | 470 base::PlatformThread::CreateNonJoinable(0, thread); |
192 } else { | 471 } else { |
193 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; | 472 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; |
194 } | 473 } |
195 } | 474 } |
196 } | 475 } |
197 | 476 |
198 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, | 477 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, |
199 int child_process_id) { | 478 int child_process_id, |
| 479 bool is_gpu_process) { |
200 lock_.AssertAcquired(); | 480 lock_.AssertAcquired(); |
201 | 481 |
202 DCHECK_EQ(0u, mach_map_.count(pid)); | 482 DCHECK_EQ(0u, mach_map_.count(pid)); |
203 mach_map_[pid] = MACH_PORT_NULL; | 483 mach_map_[pid] = MachPortSet(is_gpu_process); |
204 child_process_id_map_[child_process_id] = pid; | 484 child_process_id_map_[child_process_id] = pid; |
205 } | 485 } |
206 | 486 |
207 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { | 487 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { |
208 base::AutoLock lock(lock_); | 488 base::AutoLock lock(lock_); |
209 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); | 489 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); |
210 if (it == mach_map_.end()) | 490 if (it == mach_map_.end()) |
211 return MACH_PORT_NULL; | 491 return MACH_PORT_NULL; |
212 return it->second; | 492 return it->second.task_port; |
213 } | 493 } |
214 | 494 |
215 void MachBroker::BrowserChildProcessHostDisconnected( | 495 void MachBroker::BrowserChildProcessHostDisconnected( |
216 const ChildProcessData& data) { | 496 const ChildProcessData& data) { |
217 InvalidateChildProcessId(data.id); | 497 InvalidateChildProcessId(data.id); |
218 } | 498 } |
219 | 499 |
220 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data, | 500 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data, |
221 int exit_code) { | 501 int exit_code) { |
222 InvalidateChildProcessId(data.id); | 502 InvalidateChildProcessId(data.id); |
(...skipping 24 matching lines...) Expand all Loading... |
247 mach_port_t task_port) { | 527 mach_port_t task_port) { |
248 lock_.AssertAcquired(); | 528 lock_.AssertAcquired(); |
249 | 529 |
250 MachMap::iterator it = mach_map_.find(pid); | 530 MachMap::iterator it = mach_map_.find(pid); |
251 if (it == mach_map_.end()) { | 531 if (it == mach_map_.end()) { |
252 // Do nothing for unknown pids. | 532 // Do nothing for unknown pids. |
253 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; | 533 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; |
254 return; | 534 return; |
255 } | 535 } |
256 | 536 |
257 DCHECK(it->second == MACH_PORT_NULL); | 537 if (it->second.task_port == MACH_PORT_NULL) |
258 if (it->second == MACH_PORT_NULL) | 538 it->second.task_port = task_port; |
259 it->second = task_port; | |
260 } | 539 } |
261 | 540 |
262 void MachBroker::InvalidateChildProcessId(int child_process_id) { | 541 void MachBroker::InvalidateChildProcessId(int child_process_id) { |
263 base::AutoLock lock(lock_); | 542 base::AutoLock lock(lock_); |
264 MachBroker::ChildProcessIdMap::iterator it = | 543 MachBroker::ChildProcessIdMap::iterator it = |
265 child_process_id_map_.find(child_process_id); | 544 child_process_id_map_.find(child_process_id); |
266 if (it == child_process_id_map_.end()) | 545 if (it == child_process_id_map_.end()) |
267 return; | 546 return; |
268 | 547 |
269 MachMap::iterator mach_it = mach_map_.find(it->second); | 548 MachMap::iterator mach_it = mach_map_.find(it->second); |
270 if (mach_it != mach_map_.end()) { | 549 if (mach_it != mach_map_.end()) { |
271 kern_return_t kr = mach_port_deallocate(mach_task_self(), | 550 kern_return_t kr = |
272 mach_it->second); | 551 mach_port_deallocate(mach_task_self(), mach_it->second.task_port); |
273 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 552 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; |
| 553 for (const auto& io_surface_port : mach_it->second.io_surface_ports) { |
| 554 kr = mach_port_deallocate(mach_task_self(), io_surface_port.second); |
| 555 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; |
| 556 } |
274 mach_map_.erase(mach_it); | 557 mach_map_.erase(mach_it); |
275 } | 558 } |
276 child_process_id_map_.erase(it); | 559 child_process_id_map_.erase(it); |
277 } | 560 } |
278 | 561 |
| 562 bool MachBroker::RegisterIOSurface(base::ProcessHandle pid, |
| 563 int io_surface_id, |
| 564 int client_id, |
| 565 mach_port_t io_surface_port) { |
| 566 lock_.AssertAcquired(); |
| 567 |
| 568 MachMap::iterator mach_it = mach_map_.find(pid); |
| 569 if (mach_it == mach_map_.end()) { |
| 570 // Do nothing for unknown pids. |
| 571 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; |
| 572 return false; |
| 573 } |
| 574 |
| 575 if (!mach_it->second.is_gpu_process) { |
| 576 LOG(ERROR) << "Illegal message from non-GPU process!"; |
| 577 return false; |
| 578 } |
| 579 |
| 580 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id); |
| 581 if (it == child_process_id_map_.end()) |
| 582 return false; |
| 583 |
| 584 MachMap::iterator client_it = mach_map_.find(it->second); |
| 585 if (client_it == mach_map_.end()) { |
| 586 LOG(ERROR) << "Unknown client process " << it->second; |
| 587 return false; |
| 588 } |
| 589 |
| 590 if (client_it->second.io_surface_ports.count(io_surface_id)) { |
| 591 LOG(ERROR) << "IOSurface " << io_surface_id << " already exists!"; |
| 592 return false; |
| 593 } |
| 594 |
| 595 client_it->second.io_surface_ports[io_surface_id] = io_surface_port; |
| 596 return true; |
| 597 } |
| 598 |
| 599 void MachBroker::UnregisterIOSurface(base::ProcessHandle pid, |
| 600 int io_surface_id, |
| 601 int client_id) { |
| 602 lock_.AssertAcquired(); |
| 603 |
| 604 MachMap::iterator mach_it = mach_map_.find(pid); |
| 605 if (mach_it == mach_map_.end()) { |
| 606 // Do nothing for unknown pids. |
| 607 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; |
| 608 return; |
| 609 } |
| 610 |
| 611 if (!mach_it->second.is_gpu_process) { |
| 612 LOG(ERROR) << "Illegal message from non-GPU process!"; |
| 613 return; |
| 614 } |
| 615 |
| 616 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id); |
| 617 if (it == child_process_id_map_.end()) |
| 618 return; |
| 619 |
| 620 mach_it = mach_map_.find(it->second); |
| 621 if (mach_it != mach_map_.end()) { |
| 622 auto io_surface_mach_it = |
| 623 mach_it->second.io_surface_ports.find(io_surface_id); |
| 624 if (io_surface_mach_it != mach_it->second.io_surface_ports.end()) { |
| 625 kern_return_t kr = |
| 626 mach_port_deallocate(mach_task_self(), io_surface_mach_it->second); |
| 627 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; |
| 628 mach_it->second.io_surface_ports.erase(io_surface_mach_it); |
| 629 } |
| 630 } |
| 631 } |
| 632 |
| 633 mach_port_t MachBroker::AcquireIOSurface(base::ProcessHandle pid, |
| 634 int io_surface_id) { |
| 635 lock_.AssertAcquired(); |
| 636 |
| 637 MachMap::iterator it = mach_map_.find(pid); |
| 638 if (it == mach_map_.end()) { |
| 639 // Do nothing for unknown pids. |
| 640 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; |
| 641 return MACH_PORT_NULL; |
| 642 } |
| 643 |
| 644 auto io_surface_mach_it = it->second.io_surface_ports.find(io_surface_id); |
| 645 if (io_surface_mach_it == it->second.io_surface_ports.end()) { |
| 646 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id; |
| 647 return MACH_PORT_NULL; |
| 648 } |
| 649 |
| 650 return io_surface_mach_it->second; |
| 651 } |
| 652 |
279 // static | 653 // static |
280 std::string MachBroker::GetMachPortName() { | 654 std::string MachBroker::GetMachPortName() { |
281 const base::CommandLine* command_line = | 655 const base::CommandLine* command_line = |
282 base::CommandLine::ForCurrentProcess(); | 656 base::CommandLine::ForCurrentProcess(); |
283 const bool is_child = command_line->HasSwitch(switches::kProcessType); | 657 const bool is_child = command_line->HasSwitch(switches::kProcessType); |
284 | 658 |
285 // In non-browser (child) processes, use the parent's pid. | 659 // In non-browser (child) processes, use the parent's pid. |
286 const pid_t pid = is_child ? getppid() : getpid(); | 660 const pid_t pid = is_child ? getppid() : getpid(); |
287 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); | 661 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); |
288 } | 662 } |
289 | 663 |
290 void MachBroker::RegisterNotifications() { | 664 void MachBroker::RegisterNotifications() { |
291 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, | 665 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, |
292 NotificationService::AllBrowserContextsAndSources()); | 666 NotificationService::AllBrowserContextsAndSources()); |
293 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 667 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
294 NotificationService::AllBrowserContextsAndSources()); | 668 NotificationService::AllBrowserContextsAndSources()); |
295 | 669 |
296 // No corresponding StopObservingBrowserChildProcesses, | 670 // No corresponding StopObservingBrowserChildProcesses, |
297 // we leak this singleton. | 671 // we leak this singleton. |
298 BrowserChildProcessObserver::Add(this); | 672 BrowserChildProcessObserver::Add(this); |
299 } | 673 } |
300 | 674 |
301 } // namespace content | 675 } // namespace content |
OLD | NEW |