OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/zygote/zygote_linux.h" | 5 #include "content/zygote/zygote_linux.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 23 matching lines...) Expand all Loading... |
34 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 34 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
35 | 35 |
36 namespace content { | 36 namespace content { |
37 | 37 |
38 namespace { | 38 namespace { |
39 | 39 |
40 // NOP function. See below where this handler is installed. | 40 // NOP function. See below where this handler is installed. |
41 void SIGCHLDHandler(int signal) { | 41 void SIGCHLDHandler(int signal) { |
42 } | 42 } |
43 | 43 |
| 44 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) { |
| 45 for (size_t index = 0; index < fd_mapping.size(); ++index) { |
| 46 if (fd_mapping[index].first == key) |
| 47 return fd_mapping[index].second; |
| 48 } |
| 49 return -1; |
| 50 } |
| 51 |
44 } // namespace | 52 } // namespace |
45 | 53 |
46 Zygote::Zygote(int sandbox_flags, | 54 Zygote::Zygote(int sandbox_flags, |
47 ZygoteForkDelegate* helper) | 55 ZygoteForkDelegate* helper) |
48 : sandbox_flags_(sandbox_flags), | 56 : sandbox_flags_(sandbox_flags), |
49 helper_(helper), | 57 helper_(helper), |
50 initial_uma_sample_(0), | 58 initial_uma_sample_(0), |
51 initial_uma_boundary_value_(0) { | 59 initial_uma_boundary_value_(0) { |
52 if (helper_) { | 60 if (helper_) { |
53 helper_->InitialUMA(&initial_uma_name_, | 61 helper_->InitialUMA(&initial_uma_name_, |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 Pickle write_pickle; | 275 Pickle write_pickle; |
268 write_pickle.WriteInt(static_cast<int>(status)); | 276 write_pickle.WriteInt(static_cast<int>(status)); |
269 write_pickle.WriteInt(exit_code); | 277 write_pickle.WriteInt(exit_code); |
270 ssize_t written = | 278 ssize_t written = |
271 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); | 279 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); |
272 if (written != static_cast<ssize_t>(write_pickle.size())) | 280 if (written != static_cast<ssize_t>(write_pickle.size())) |
273 PLOG(ERROR) << "write"; | 281 PLOG(ERROR) << "write"; |
274 } | 282 } |
275 | 283 |
276 int Zygote::ForkWithRealPid(const std::string& process_type, | 284 int Zygote::ForkWithRealPid(const std::string& process_type, |
277 std::vector<int>& fds, | 285 const base::GlobalDescriptors::Mapping& fd_mapping, |
278 const std::string& channel_switch, | 286 const std::string& channel_switch, |
279 std::string* uma_name, | 287 std::string* uma_name, |
280 int* uma_sample, | 288 int* uma_sample, |
281 int* uma_boundary_value) { | 289 int* uma_boundary_value) { |
282 const bool use_helper = (helper_ && helper_->CanHelp(process_type, | 290 const bool use_helper = (helper_ && helper_->CanHelp(process_type, |
283 uma_name, | 291 uma_name, |
284 uma_sample, | 292 uma_sample, |
285 uma_boundary_value)); | 293 uma_boundary_value)); |
286 int dummy_fd; | 294 int dummy_fd; |
287 ino_t dummy_inode; | 295 ino_t dummy_inode; |
288 int pipe_fds[2] = { -1, -1 }; | 296 int pipe_fds[2] = { -1, -1 }; |
289 base::ProcessId pid = 0; | 297 base::ProcessId pid = 0; |
290 | 298 |
291 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | 299 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
292 if (dummy_fd < 0) { | 300 if (dummy_fd < 0) { |
293 LOG(ERROR) << "Failed to create dummy FD"; | 301 LOG(ERROR) << "Failed to create dummy FD"; |
294 goto error; | 302 goto error; |
295 } | 303 } |
296 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { | 304 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { |
297 LOG(ERROR) << "Failed to get inode for dummy FD"; | 305 LOG(ERROR) << "Failed to get inode for dummy FD"; |
298 goto error; | 306 goto error; |
299 } | 307 } |
300 if (pipe(pipe_fds) != 0) { | 308 if (pipe(pipe_fds) != 0) { |
301 LOG(ERROR) << "Failed to create pipe"; | 309 LOG(ERROR) << "Failed to create pipe"; |
302 goto error; | 310 goto error; |
303 } | 311 } |
304 | 312 |
305 if (use_helper) { | 313 if (use_helper) { |
306 fds.push_back(dummy_fd); | 314 std::vector<int> fds; |
307 fds.push_back(pipe_fds[0]); | 315 int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel); |
| 316 if (ipc_channel_fd < 0) { |
| 317 DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping"; |
| 318 goto error; |
| 319 } |
| 320 fds.push_back(ipc_channel_fd); // kBrowserFDIndex |
| 321 fds.push_back(dummy_fd); // kDummyFDIndex |
| 322 fds.push_back(pipe_fds[0]); // kParentFDIndex |
308 pid = helper_->Fork(fds); | 323 pid = helper_->Fork(fds); |
309 } else { | 324 } else { |
310 pid = fork(); | 325 pid = fork(); |
311 } | 326 } |
312 if (pid < 0) { | 327 if (pid < 0) { |
313 goto error; | 328 goto error; |
314 } else if (pid == 0) { | 329 } else if (pid == 0) { |
315 // In the child process. | 330 // In the child process. |
316 close(pipe_fds[1]); | 331 close(pipe_fds[1]); |
317 base::ProcessId real_pid; | 332 base::ProcessId real_pid; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 base::GlobalDescriptors::Key key; | 467 base::GlobalDescriptors::Key key; |
453 if (!pickle.ReadUInt32(&iter, &key)) | 468 if (!pickle.ReadUInt32(&iter, &key)) |
454 return -1; | 469 return -1; |
455 mapping.push_back(std::make_pair(key, fds[i])); | 470 mapping.push_back(std::make_pair(key, fds[i])); |
456 } | 471 } |
457 | 472 |
458 mapping.push_back(std::make_pair( | 473 mapping.push_back(std::make_pair( |
459 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); | 474 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); |
460 | 475 |
461 // Returns twice, once per process. | 476 // Returns twice, once per process. |
462 base::ProcessId child_pid = ForkWithRealPid(process_type, fds, channel_id, | 477 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id, |
463 uma_name, uma_sample, | 478 uma_name, uma_sample, |
464 uma_boundary_value); | 479 uma_boundary_value); |
465 if (!child_pid) { | 480 if (!child_pid) { |
466 // This is the child process. | 481 // This is the child process. |
467 | 482 |
468 close(kZygoteSocketPairFd); // Our socket from the browser. | 483 close(kZygoteSocketPairFd); // Our socket from the browser. |
469 if (UsingSUIDSandbox()) | 484 if (UsingSUIDSandbox()) |
470 close(kZygoteIdFd); // Another socket from the browser. | 485 close(kZygoteIdFd); // Another socket from the browser. |
471 base::GlobalDescriptors::GetInstance()->Reset(mapping); | 486 base::GlobalDescriptors::GetInstance()->Reset(mapping); |
472 | 487 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 PickleIterator iter) { | 544 PickleIterator iter) { |
530 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != | 545 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != |
531 sizeof(sandbox_flags_)) { | 546 sizeof(sandbox_flags_)) { |
532 PLOG(ERROR) << "write"; | 547 PLOG(ERROR) << "write"; |
533 } | 548 } |
534 | 549 |
535 return false; | 550 return false; |
536 } | 551 } |
537 | 552 |
538 } // namespace content | 553 } // namespace content |
OLD | NEW |