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

Side by Side Diff: content/zygote/zygote_linux.cc

Issue 1057403002: Start all children in their own PID namespace. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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 | « content/common/sandbox_linux/sandbox_linux.cc ('k') | content/zygote/zygote_main_linux.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 (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 18 matching lines...) Expand all
29 #include "content/common/sandbox_linux/sandbox_linux.h" 29 #include "content/common/sandbox_linux/sandbox_linux.h"
30 #include "content/common/set_process_title.h" 30 #include "content/common/set_process_title.h"
31 #include "content/common/zygote_commands_linux.h" 31 #include "content/common/zygote_commands_linux.h"
32 #include "content/public/common/content_descriptors.h" 32 #include "content/public/common/content_descriptors.h"
33 #include "content/public/common/result_codes.h" 33 #include "content/public/common/result_codes.h"
34 #include "content/public/common/sandbox_linux.h" 34 #include "content/public/common/sandbox_linux.h"
35 #include "content/public/common/send_zygote_child_ping_linux.h" 35 #include "content/public/common/send_zygote_child_ping_linux.h"
36 #include "content/public/common/zygote_fork_delegate_linux.h" 36 #include "content/public/common/zygote_fork_delegate_linux.h"
37 #include "ipc/ipc_channel.h" 37 #include "ipc/ipc_channel.h"
38 #include "ipc/ipc_switches.h" 38 #include "ipc/ipc_switches.h"
39 #include "sandbox/linux/services/credentials.h"
40 #include "sandbox/linux/services/namespace_sandbox.h"
39 41
40 // See http://code.google.com/p/chromium/wiki/LinuxZygote 42 // See http://code.google.com/p/chromium/wiki/LinuxZygote
41 43
42 namespace content { 44 namespace content {
43 45
44 namespace { 46 namespace {
45 47
46 // NOP function. See below where this handler is installed. 48 // NOP function. See below where this handler is installed.
47 void SIGCHLDHandler(int signal) { 49 void SIGCHLDHandler(int signal) {
48 } 50 }
49 51
52 // On Linux, when a process is the init process of a PID namespace, it cannot be
53 // terminated by signals like SIGTERM or SIGINT, since they are ignored unless
54 // we register a handler for them. In the handlers, we exit with this special
55 // exit code that GetTerminationStatus understands to mean that we were
56 // terminated by an external signal.
57 const int kKilledExitCode = 0x80;
58 const int kUnexpectedExitCode = 0x81;
59
50 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) { 60 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
51 for (size_t index = 0; index < fd_mapping.size(); ++index) { 61 for (size_t index = 0; index < fd_mapping.size(); ++index) {
52 if (fd_mapping[index].key == key) 62 if (fd_mapping[index].key == key)
53 return fd_mapping[index].fd; 63 return fd_mapping[index].fd;
54 } 64 }
55 return -1; 65 return -1;
56 } 66 }
57 67
58 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { 68 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
59 int raw_pipe[2]; 69 int raw_pipe[2];
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the 107 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
98 // browser on it. 108 // browser on it.
99 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. 109 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
100 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC 110 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
101 111
102 // We need to accept SIGCHLD, even though our handler is a no-op because 112 // We need to accept SIGCHLD, even though our handler is a no-op because
103 // otherwise we cannot wait on children. (According to POSIX 2001.) 113 // otherwise we cannot wait on children. (According to POSIX 2001.)
104 struct sigaction action; 114 struct sigaction action;
105 memset(&action, 0, sizeof(action)); 115 memset(&action, 0, sizeof(action));
106 action.sa_handler = &SIGCHLDHandler; 116 action.sa_handler = &SIGCHLDHandler;
107 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); 117 PCHECK(sigaction(SIGCHLD, &action, NULL) == 0);
108 118
109 if (UsingSUIDSandbox() || UsingNSSandbox()) { 119 if (UsingSUIDSandbox() || UsingNSSandbox()) {
110 // Let the ZygoteHost know we are ready to go. 120 // Let the ZygoteHost know we are ready to go.
111 // The receiving code is in content/browser/zygote_host_linux.cc. 121 // The receiving code is in content/browser/zygote_host_linux.cc.
112 bool r = UnixDomainSocket::SendMsg(kZygoteSocketPairFd, 122 bool r = UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
113 kZygoteHelloMessage, 123 kZygoteHelloMessage,
114 sizeof(kZygoteHelloMessage), 124 sizeof(kZygoteHelloMessage),
115 std::vector<int>()); 125 std::vector<int>());
116 #if defined(OS_CHROMEOS) 126 #if defined(OS_CHROMEOS)
117 LOG_IF(WARNING, !r) << "Sending zygote magic failed"; 127 LOG_IF(WARNING, !r) << "Sending zygote magic failed";
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 // We don't know if the process is dying, so get its status but don't 308 // We don't know if the process is dying, so get its status but don't
299 // wait. 309 // wait.
300 *status = base::GetTerminationStatus(child, exit_code); 310 *status = base::GetTerminationStatus(child, exit_code);
301 } 311 }
302 } 312 }
303 // Successfully got a status for |real_pid|. 313 // Successfully got a status for |real_pid|.
304 if (*status != base::TERMINATION_STATUS_STILL_RUNNING) { 314 if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
305 // Time to forget about this process. 315 // Time to forget about this process.
306 process_info_map_.erase(real_pid); 316 process_info_map_.erase(real_pid);
307 } 317 }
318
319 if (WIFEXITED(*exit_code) && WEXITSTATUS(*exit_code) == kKilledExitCode) {
320 *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
321 }
322
308 return true; 323 return true;
309 } 324 }
310 325
311 void Zygote::HandleGetTerminationStatus(int fd, 326 void Zygote::HandleGetTerminationStatus(int fd,
312 PickleIterator iter) { 327 PickleIterator iter) {
313 bool known_dead; 328 bool known_dead;
314 base::ProcessHandle child_requested; 329 base::ProcessHandle child_requested;
315 330
316 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) { 331 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) {
317 LOG(WARNING) << "Error parsing GetTerminationStatus request " 332 LOG(WARNING) << "Error parsing GetTerminationStatus request "
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 383 }
369 std::vector<int> fds; 384 std::vector<int> fds;
370 fds.push_back(ipc_channel_fd); // kBrowserFDIndex 385 fds.push_back(ipc_channel_fd); // kBrowserFDIndex
371 fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex 386 fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
372 pid = helper->Fork(process_type, fds, channel_id); 387 pid = helper->Fork(process_type, fds, channel_id);
373 388
374 // Helpers should never return in the child process. 389 // Helpers should never return in the child process.
375 CHECK_NE(pid, 0); 390 CHECK_NE(pid, 0);
376 } else { 391 } else {
377 CreatePipe(&read_pipe, &write_pipe); 392 CreatePipe(&read_pipe, &write_pipe);
378 // This is roughly equivalent to a fork(). We are using ForkWithFlags mainly 393 if (sandbox_flags_ & kSandboxLinuxPIDNS &&
379 // to give it some more diverse test coverage. 394 sandbox_flags_ & kSandboxLinuxUserNS) {
380 pid = base::ForkWithFlags(SIGCHLD, nullptr, nullptr); 395 pid = sandbox::NamespaceSandbox::ForkInNewPidNamespace(
396 /*drop_capabilities_in_child=*/true);
397 } else {
398 pid = fork();
399 }
381 } 400 }
382 401
383 if (pid == 0) { 402 if (pid == 0) {
403 // If the process is the init process inside a PID namespace, it must have
404 // explicit signal handlers.
405 if (getpid() == 1) {
406 for (const int sig : {SIGINT, SIGTERM}) {
407 sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
408 sig, kKilledExitCode);
409 }
410
411 static const int kUnexpectedSignals[] = {
412 SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, SIGUSR1, SIGUSR2,
413 };
414 for (const int sig : kUnexpectedSignals) {
415 sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
416 sig, kUnexpectedExitCode);
417 }
418 }
419
384 // In the child process. 420 // In the child process.
385 write_pipe.reset(); 421 write_pipe.reset();
386 422
387 // Ping the PID oracle socket so the browser can find our PID. 423 // Ping the PID oracle socket so the browser can find our PID.
388 CHECK(SendZygoteChildPing(pid_oracle.get())); 424 CHECK(SendZygoteChildPing(pid_oracle.get()));
389 425
390 // Now read back our real PID from the zygote. 426 // Now read back our real PID from the zygote.
391 base::ProcessId real_pid; 427 base::ProcessId real_pid;
392 if (!base::ReadFromFD(read_pipe.get(), 428 if (!base::ReadFromFD(read_pipe.get(),
393 reinterpret_cast<char*>(&real_pid), 429 reinterpret_cast<char*>(&real_pid),
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 PickleIterator iter) { 621 PickleIterator iter) {
586 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 622 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
587 sizeof(sandbox_flags_)) { 623 sizeof(sandbox_flags_)) {
588 PLOG(ERROR) << "write"; 624 PLOG(ERROR) << "write";
589 } 625 }
590 626
591 return false; 627 return false;
592 } 628 }
593 629
594 } // namespace content 630 } // namespace content
OLDNEW
« no previous file with comments | « content/common/sandbox_linux/sandbox_linux.cc ('k') | content/zygote/zygote_main_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698