| 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_main.h" | 5 #include "content/zygote/zygote_main.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <pthread.h> | 9 #include <pthread.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| 11 #include <sys/socket.h> | 11 #include <sys/socket.h> |
| 12 #include <sys/stat.h> | 12 #include <sys/stat.h> |
| 13 #include <sys/types.h> | 13 #include <sys/types.h> |
| 14 #include <sys/wait.h> | 14 #include <sys/wait.h> |
| 15 #include <unistd.h> | 15 #include <unistd.h> |
| 16 | 16 |
| 17 #include "base/basictypes.h" | 17 #include "base/basictypes.h" |
| 18 #include "base/bind.h" |
| 19 #include "base/callback.h" |
| 18 #include "base/command_line.h" | 20 #include "base/command_line.h" |
| 19 #include "base/linux_util.h" | 21 #include "base/linux_util.h" |
| 20 #include "base/native_library.h" | 22 #include "base/native_library.h" |
| 21 #include "base/pickle.h" | 23 #include "base/pickle.h" |
| 22 #include "base/posix/eintr_wrapper.h" | 24 #include "base/posix/eintr_wrapper.h" |
| 23 #include "base/posix/unix_domain_socket_linux.h" | 25 #include "base/posix/unix_domain_socket_linux.h" |
| 24 #include "base/rand_util.h" | 26 #include "base/rand_util.h" |
| 25 #include "base/sys_info.h" | 27 #include "base/sys_info.h" |
| 26 #include "build/build_config.h" | 28 #include "build/build_config.h" |
| 27 #include "content/common/child_process_sandbox_support_impl_linux.h" | 29 #include "content/common/child_process_sandbox_support_impl_linux.h" |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 // Ensure access to the Pepper plugins before the sandbox is turned on. | 303 // Ensure access to the Pepper plugins before the sandbox is turned on. |
| 302 PreloadPepperPlugins(); | 304 PreloadPepperPlugins(); |
| 303 #endif | 305 #endif |
| 304 #if defined(ENABLE_WEBRTC) | 306 #if defined(ENABLE_WEBRTC) |
| 305 InitializeWebRtcModule(); | 307 InitializeWebRtcModule(); |
| 306 #endif | 308 #endif |
| 307 SkFontConfigInterface::SetGlobal( | 309 SkFontConfigInterface::SetGlobal( |
| 308 new FontConfigIPC(GetSandboxFD()))->unref(); | 310 new FontConfigIPC(GetSandboxFD()))->unref(); |
| 309 } | 311 } |
| 310 | 312 |
| 311 // Do nothing here | 313 static void CloseFdAndHandleEintr(int fd) { |
| 312 static void SIGCHLDHandler(int signal) { | 314 (void) HANDLE_EINTR(close(fd)); |
| 313 } | |
| 314 | |
| 315 // The current process will become a process reaper like init. | |
| 316 // We fork a child that will continue normally, when it dies, we can safely | |
| 317 // exit. | |
| 318 // We need to be careful we close the magic kZygoteIdFd properly in the parent | |
| 319 // before this function returns. | |
| 320 static bool CreateInitProcessReaper() { | |
| 321 int sync_fds[2]; | |
| 322 // We want to use send, so we can't use a pipe | |
| 323 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) { | |
| 324 LOG(ERROR) << "Failed to create socketpair"; | |
| 325 return false; | |
| 326 } | |
| 327 | |
| 328 // We use normal fork, not the ForkDelegate in this case since we are not a | |
| 329 // true Zygote yet. | |
| 330 pid_t child_pid = fork(); | |
| 331 if (child_pid == -1) { | |
| 332 (void) HANDLE_EINTR(close(sync_fds[0])); | |
| 333 (void) HANDLE_EINTR(close(sync_fds[1])); | |
| 334 return false; | |
| 335 } | |
| 336 if (child_pid) { | |
| 337 // We are the parent, assuming the role of an init process. | |
| 338 // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return | |
| 339 // once all of our childs are dead. Since we're init we need to reap childs | |
| 340 // as they come. | |
| 341 struct sigaction action; | |
| 342 memset(&action, 0, sizeof(action)); | |
| 343 action.sa_handler = &SIGCHLDHandler; | |
| 344 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); | |
| 345 | |
| 346 (void) HANDLE_EINTR(close(sync_fds[0])); | |
| 347 shutdown(sync_fds[1], SHUT_RD); | |
| 348 // This "magic" socket must only appear in one process. | |
| 349 (void) HANDLE_EINTR(close(kZygoteIdFd)); | |
| 350 // Tell the child to continue | |
| 351 CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1); | |
| 352 (void) HANDLE_EINTR(close(sync_fds[1])); | |
| 353 | |
| 354 for (;;) { | |
| 355 // Loop until we have reaped our one natural child | |
| 356 siginfo_t reaped_child_info; | |
| 357 int wait_ret = | |
| 358 HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED)); | |
| 359 if (wait_ret) | |
| 360 _exit(1); | |
| 361 if (reaped_child_info.si_pid == child_pid) { | |
| 362 int exit_code = 0; | |
| 363 // We're done waiting | |
| 364 if (reaped_child_info.si_code == CLD_EXITED) { | |
| 365 exit_code = reaped_child_info.si_status; | |
| 366 } | |
| 367 // Exit with the same exit code as our parent. This is most likely | |
| 368 // useless. _exit with 0 if we got signaled. | |
| 369 _exit(exit_code); | |
| 370 } | |
| 371 } | |
| 372 } else { | |
| 373 // The child needs to wait for the parent to close kZygoteIdFd to avoid a | |
| 374 // race condition | |
| 375 (void) HANDLE_EINTR(close(sync_fds[1])); | |
| 376 shutdown(sync_fds[0], SHUT_WR); | |
| 377 char should_continue; | |
| 378 int read_ret = HANDLE_EINTR(read(sync_fds[0], &should_continue, 1)); | |
| 379 (void) HANDLE_EINTR(close(sync_fds[0])); | |
| 380 if (read_ret == 1) | |
| 381 return true; | |
| 382 else | |
| 383 return false; | |
| 384 } | |
| 385 } | 315 } |
| 386 | 316 |
| 387 // This will set the *using_suid_sandbox variable to true if the SUID sandbox | 317 // This will set the *using_suid_sandbox variable to true if the SUID sandbox |
| 388 // is enabled. This does not necessarily exclude other types of sandboxing. | 318 // is enabled. This does not necessarily exclude other types of sandboxing. |
| 389 static bool EnterSuidSandbox(LinuxSandbox* linux_sandbox, | 319 static bool EnterSuidSandbox(LinuxSandbox* linux_sandbox, |
| 390 bool* using_suid_sandbox, | 320 bool* using_suid_sandbox, |
| 391 bool* has_started_new_init) { | 321 bool* has_started_new_init) { |
| 392 *using_suid_sandbox = false; | 322 *using_suid_sandbox = false; |
| 393 *has_started_new_init = false; | 323 *has_started_new_init = false; |
| 394 | 324 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 414 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." | 344 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." |
| 415 "\n\n"; | 345 "\n\n"; |
| 416 } | 346 } |
| 417 | 347 |
| 418 if (!setuid_sandbox->ChrootMe()) | 348 if (!setuid_sandbox->ChrootMe()) |
| 419 return false; | 349 return false; |
| 420 | 350 |
| 421 if (getpid() == 1) { | 351 if (getpid() == 1) { |
| 422 // The setuid sandbox has created a new PID namespace and we need | 352 // The setuid sandbox has created a new PID namespace and we need |
| 423 // to assume the role of init. | 353 // to assume the role of init. |
| 424 if (!CreateInitProcessReaper()) { | 354 // This "magic" socket must only appear in one process, so make sure |
| 355 // it gets closed in the parent after fork(). |
| 356 base::Closure zygoteid_fd_closer = |
| 357 base::Bind(CloseFdAndHandleEintr, kZygoteIdFd); |
| 358 const bool init_created = |
| 359 setuid_sandbox->CreateInitProcessReaper(&zygoteid_fd_closer); |
| 360 if (!init_created) { |
| 425 LOG(ERROR) << "Error creating an init process to reap zombies"; | 361 LOG(ERROR) << "Error creating an init process to reap zombies"; |
| 426 return false; | 362 return false; |
| 427 } | 363 } |
| 428 *has_started_new_init = true; | 364 *has_started_new_init = true; |
| 429 } | 365 } |
| 430 | 366 |
| 431 #if !defined(OS_OPENBSD) | 367 #if !defined(OS_OPENBSD) |
| 432 // Previously, we required that the binary be non-readable. This causes the | 368 // Previously, we required that the binary be non-readable. This causes the |
| 433 // kernel to mark the process as non-dumpable at startup. The thinking was | 369 // kernel to mark the process as non-dumpable at startup. The thinking was |
| 434 // that, although we were putting the renderers into a PID namespace (with | 370 // that, although we were putting the renderers into a PID namespace (with |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 } | 434 } |
| 499 | 435 |
| 500 int sandbox_flags = linux_sandbox->GetStatus(); | 436 int sandbox_flags = linux_sandbox->GetStatus(); |
| 501 | 437 |
| 502 Zygote zygote(sandbox_flags, forkdelegate); | 438 Zygote zygote(sandbox_flags, forkdelegate); |
| 503 // This function call can return multiple times, once per fork(). | 439 // This function call can return multiple times, once per fork(). |
| 504 return zygote.ProcessRequests(); | 440 return zygote.ProcessRequests(); |
| 505 } | 441 } |
| 506 | 442 |
| 507 } // namespace content | 443 } // namespace content |
| OLD | NEW |