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

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: Created 5 years, 10 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 | « no previous file | content/zygote/zygote_main_linux.cc » ('j') | content/zygote/zygote_main_linux.cc » ('J')
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"
39 40
40 #if defined(ADDRESS_SANITIZER) 41 #if defined(ADDRESS_SANITIZER)
41 #include <sanitizer/asan_interface.h> 42 #include <sanitizer/asan_interface.h>
42 #endif 43 #endif
43 44
44 // See http://code.google.com/p/chromium/wiki/LinuxZygote 45 // See http://code.google.com/p/chromium/wiki/LinuxZygote
45 46
46 namespace content { 47 namespace content {
47 48
48 namespace { 49 namespace {
49 50
50 // NOP function. See below where this handler is installed. 51 // NOP function. See below where this handler is installed.
51 void SIGCHLDHandler(int signal) { 52 void SIGCHLDHandler(int signal) {
52 } 53 }
53 54
55 // On Linux, when a process is the init process of a PID namespace, it cannot be
56 // terminated by signals like SIGTERM or SIGINT, since they are ignored unless
57 // we register a handler for them. In the handlers, we exit with this special
58 // exit code that GetTerminationStatus understands to mean that we were
59 // terminated by an external signal.
60 const int kKilledExitCode = 0x80;
61
62 void TerminationSignalHandler(int signal) {
63 // Return a special exit code so that the process is detected as terminated by
64 // a signal. We cannot terminate ourself with a signal since we may be the
65 // init process in a PID namespace.
66 _exit(kKilledExitCode);
67 }
68
54 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) { 69 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
55 for (size_t index = 0; index < fd_mapping.size(); ++index) { 70 for (size_t index = 0; index < fd_mapping.size(); ++index) {
56 if (fd_mapping[index].key == key) 71 if (fd_mapping[index].key == key)
57 return fd_mapping[index].fd; 72 return fd_mapping[index].fd;
58 } 73 }
59 return -1; 74 return -1;
60 } 75 }
61 76
62 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { 77 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
63 int raw_pipe[2]; 78 int raw_pipe[2];
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 GetTerminationStatus(child, true /* known_dead */, &status, &exit_code); 282 GetTerminationStatus(child, true /* known_dead */, &status, &exit_code);
268 DCHECK(got_termination_status); 283 DCHECK(got_termination_status);
269 } 284 }
270 process_info_map_.erase(child); 285 process_info_map_.erase(child);
271 } 286 }
272 287
273 bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid, 288 bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
274 bool known_dead, 289 bool known_dead,
275 base::TerminationStatus* status, 290 base::TerminationStatus* status,
276 int* exit_code) { 291 int* exit_code) {
277
278 ZygoteProcessInfo child_info; 292 ZygoteProcessInfo child_info;
279 if (!GetProcessInfo(real_pid, &child_info)) { 293 if (!GetProcessInfo(real_pid, &child_info)) {
280 LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID " 294 LOG(FATAL) << "Zygote::GetTerminationStatus for unknown PID "
281 << real_pid; 295 << real_pid;
282 NOTREACHED();
283 return false; 296 return false;
284 } 297 }
285 // We know about |real_pid|. 298 // We know about |real_pid|.
286 const base::ProcessHandle child = child_info.internal_pid; 299 const base::ProcessHandle child = child_info.internal_pid;
287 if (child_info.started_from_helper) { 300 if (child_info.started_from_helper) {
288 if (!child_info.started_from_helper->GetTerminationStatus( 301 if (!child_info.started_from_helper->GetTerminationStatus(
289 child, known_dead, status, exit_code)) { 302 child, known_dead, status, exit_code)) {
290 return false; 303 return false;
291 } 304 }
292 } else { 305 } else {
293 // Handle the request directly. 306 // Handle the request directly.
294 if (known_dead) { 307 if (known_dead) {
295 *status = base::GetKnownDeadTerminationStatus(child, exit_code); 308 *status = base::GetKnownDeadTerminationStatus(child, exit_code);
296 } else { 309 } else {
297 // We don't know if the process is dying, so get its status but don't 310 // We don't know if the process is dying, so get its status but don't
298 // wait. 311 // wait.
299 *status = base::GetTerminationStatus(child, exit_code); 312 *status = base::GetTerminationStatus(child, exit_code);
300 } 313 }
301 } 314 }
302 // Successfully got a status for |real_pid|. 315 // Successfully got a status for |real_pid|.
303 if (*status != base::TERMINATION_STATUS_STILL_RUNNING) { 316 if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
304 // Time to forget about this process. 317 // Time to forget about this process.
305 process_info_map_.erase(real_pid); 318 process_info_map_.erase(real_pid);
306 } 319 }
320
321 if (WIFEXITED(*exit_code) && WEXITSTATUS(*exit_code) == kKilledExitCode) {
322 *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
323 }
324
307 return true; 325 return true;
308 } 326 }
309 327
310 void Zygote::HandleGetTerminationStatus(int fd, 328 void Zygote::HandleGetTerminationStatus(int fd,
311 PickleIterator iter) { 329 PickleIterator iter) {
312 bool known_dead; 330 bool known_dead;
313 base::ProcessHandle child_requested; 331 base::ProcessHandle child_requested;
314 332
315 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) { 333 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) {
316 LOG(WARNING) << "Error parsing GetTerminationStatus request " 334 LOG(WARNING) << "Error parsing GetTerminationStatus request "
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 } 385 }
368 std::vector<int> fds; 386 std::vector<int> fds;
369 fds.push_back(ipc_channel_fd); // kBrowserFDIndex 387 fds.push_back(ipc_channel_fd); // kBrowserFDIndex
370 fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex 388 fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
371 pid = helper->Fork(process_type, fds, channel_id); 389 pid = helper->Fork(process_type, fds, channel_id);
372 390
373 // Helpers should never return in the child process. 391 // Helpers should never return in the child process.
374 CHECK_NE(pid, 0); 392 CHECK_NE(pid, 0);
375 } else { 393 } else {
376 CreatePipe(&read_pipe, &write_pipe); 394 CreatePipe(&read_pipe, &write_pipe);
377 // This is roughly equivalent to a fork(). We are using ForkWithFlags mainly 395 int clone_flags = SIGCHLD;
378 // to give it some more diverse test coverage. 396 if (sandbox_flags_ & kSandboxLinuxPIDNS &&
379 pid = base::ForkWithFlags(SIGCHLD, nullptr, nullptr); 397 sandbox_flags_ & kSandboxLinuxUserNS) {
398 clone_flags |= CLONE_NEWPID;
399 }
400 pid = base::ForkWithFlags(clone_flags, nullptr, nullptr);
380 } 401 }
381 402
382 if (pid == 0) { 403 if (pid == 0) {
404 CHECK(sandbox::Credentials::DropAllCapabilities());
405
406 // If the process is the init process inside a PID namespace, it must have
407 // explicit SIGTERM and SIGINT handlers.
408 if (getpid() == 1) {
409 struct sigaction action;
410 memset(&action, 0, sizeof(action));
411 action.sa_handler = &TerminationSignalHandler;
412 PCHECK(sigaction(SIGINT, &action, nullptr) == 0);
413 PCHECK(sigaction(SIGTERM, &action, nullptr) == 0);
414 }
415
383 // In the child process. 416 // In the child process.
384 write_pipe.reset(); 417 write_pipe.reset();
385 418
386 // Ping the PID oracle socket so the browser can find our PID. 419 // Ping the PID oracle socket so the browser can find our PID.
387 CHECK(SendZygoteChildPing(pid_oracle.get())); 420 CHECK(SendZygoteChildPing(pid_oracle.get()));
388 421
389 // Now read back our real PID from the zygote. 422 // Now read back our real PID from the zygote.
390 base::ProcessId real_pid; 423 base::ProcessId real_pid;
391 if (!base::ReadFromFD(read_pipe.get(), 424 if (!base::ReadFromFD(read_pipe.get(),
392 reinterpret_cast<char*>(&real_pid), 425 reinterpret_cast<char*>(&real_pid),
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 PickleIterator iter) { 617 PickleIterator iter) {
585 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 618 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
586 sizeof(sandbox_flags_)) { 619 sizeof(sandbox_flags_)) {
587 PLOG(ERROR) << "write"; 620 PLOG(ERROR) << "write";
588 } 621 }
589 622
590 return false; 623 return false;
591 } 624 }
592 625
593 } // namespace content 626 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/zygote/zygote_main_linux.cc » ('j') | content/zygote/zygote_main_linux.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698