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

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

Issue 868233011: Start all children in their own PID namespace. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Respond to more comments. Created 5 years, 9 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
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 238 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(true);
jln (very slow on Chromium) 2015/03/25 23:47:50 /* drop_capabilities_in_child */
rickyz (no longer on Chrome) 2015/03/26 00:09:37 Done.
396 } else {
397 pid = fork();
398 }
381 } 399 }
382 400
383 if (pid == 0) { 401 if (pid == 0) {
402 // If the process is the init process inside a PID namespace, it must have
403 // explicit signal handlers.
404 if (getpid() == 1) {
405 for (const int sig : {SIGINT, SIGTERM}) {
406 sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
407 sig, kKilledExitCode);
408 }
409
410 static const int kUnexpectedSignals[] = {
411 SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, SIGUSR1, SIGUSR2,
412 };
413 for (const int sig : kUnexpectedSignals) {
414 sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
415 sig, kUnexpectedExitCode);
416 }
417 }
418
384 // In the child process. 419 // In the child process.
385 write_pipe.reset(); 420 write_pipe.reset();
386 421
387 // Ping the PID oracle socket so the browser can find our PID. 422 // Ping the PID oracle socket so the browser can find our PID.
388 CHECK(SendZygoteChildPing(pid_oracle.get())); 423 CHECK(SendZygoteChildPing(pid_oracle.get()));
389 424
390 // Now read back our real PID from the zygote. 425 // Now read back our real PID from the zygote.
391 base::ProcessId real_pid; 426 base::ProcessId real_pid;
392 if (!base::ReadFromFD(read_pipe.get(), 427 if (!base::ReadFromFD(read_pipe.get(),
393 reinterpret_cast<char*>(&real_pid), 428 reinterpret_cast<char*>(&real_pid),
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 PickleIterator iter) { 620 PickleIterator iter) {
586 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 621 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
587 sizeof(sandbox_flags_)) { 622 sizeof(sandbox_flags_)) {
588 PLOG(ERROR) << "write"; 623 PLOG(ERROR) << "write";
589 } 624 }
590 625
591 return false; 626 return false;
592 } 627 }
593 628
594 } // namespace content 629 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698