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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <pthread.h> | 7 #include <pthread.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "content/common/pepper_plugin_registry.h" | 30 #include "content/common/pepper_plugin_registry.h" |
31 #include "content/common/sandbox_methods_linux.h" | 31 #include "content/common/sandbox_methods_linux.h" |
32 #include "content/common/seccomp_sandbox.h" | 32 #include "content/common/seccomp_sandbox.h" |
33 #include "content/common/zygote_commands_linux.h" | 33 #include "content/common/zygote_commands_linux.h" |
34 #include "content/public/common/content_switches.h" | 34 #include "content/public/common/content_switches.h" |
35 #include "content/public/common/main_function_params.h" | 35 #include "content/public/common/main_function_params.h" |
36 #include "content/public/common/sandbox_linux.h" | 36 #include "content/public/common/sandbox_linux.h" |
37 #include "content/public/common/zygote_fork_delegate_linux.h" | 37 #include "content/public/common/zygote_fork_delegate_linux.h" |
38 #include "content/zygote/zygote_linux.h" | 38 #include "content/zygote/zygote_linux.h" |
39 #include "sandbox/linux/services/libc_urandom_override.h" | 39 #include "sandbox/linux/services/libc_urandom_override.h" |
| 40 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
40 #include "skia/ext/SkFontHost_fontconfig_control.h" | 41 #include "skia/ext/SkFontHost_fontconfig_control.h" |
41 #include "unicode/timezone.h" | 42 #include "unicode/timezone.h" |
42 | 43 |
43 #if defined(OS_LINUX) | 44 #if defined(OS_LINUX) |
44 #include <sys/epoll.h> | 45 #include <sys/epoll.h> |
45 #include <sys/prctl.h> | 46 #include <sys/prctl.h> |
46 #include <sys/signal.h> | 47 #include <sys/signal.h> |
47 #else | 48 #else |
48 #include <signal.h> | 49 #include <signal.h> |
49 #endif | 50 #endif |
50 | 51 |
51 namespace content { | 52 namespace content { |
52 | 53 |
53 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 54 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
54 | 55 |
55 // The SUID sandbox sets this environment variable to a file descriptor | |
56 // over which we can signal that we have completed our startup and can be | |
57 // chrooted. | |
58 static const char kSUIDSandboxVar[] = "SBX_D"; | |
59 | |
60 // With SELinux we can carve out a precise sandbox, so we don't have to play | 56 // With SELinux we can carve out a precise sandbox, so we don't have to play |
61 // with intercepting libc calls. | 57 // with intercepting libc calls. |
62 #if !defined(CHROMIUM_SELINUX) | 58 #if !defined(CHROMIUM_SELINUX) |
63 | 59 |
64 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, | 60 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, |
65 char* timezone_out, | 61 char* timezone_out, |
66 size_t timezone_out_len) { | 62 size_t timezone_out_len) { |
67 Pickle request; | 63 Pickle request; |
68 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); | 64 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); |
69 request.WriteString( | 65 request.WriteString( |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 (void) HANDLE_EINTR(close(sync_fds[0])); | 353 (void) HANDLE_EINTR(close(sync_fds[0])); |
358 if (read_ret == 1) | 354 if (read_ret == 1) |
359 return true; | 355 return true; |
360 else | 356 else |
361 return false; | 357 return false; |
362 } | 358 } |
363 } | 359 } |
364 | 360 |
365 // This will set the *using_suid_sandbox variable to true if the SUID sandbox | 361 // This will set the *using_suid_sandbox variable to true if the SUID sandbox |
366 // is enabled. This does not necessarily exclude other types of sandboxing. | 362 // is enabled. This does not necessarily exclude other types of sandboxing. |
367 static bool EnterSandbox(bool* using_suid_sandbox, bool* has_started_new_init) { | 363 static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, |
| 364 bool* using_suid_sandbox, bool* has_started_new_init) { |
368 *using_suid_sandbox = false; | 365 *using_suid_sandbox = false; |
369 *has_started_new_init = false; | 366 *has_started_new_init = false; |
| 367 if (!setuid_sandbox) |
| 368 return false; |
370 | 369 |
371 PreSandboxInit(); | 370 PreSandboxInit(); |
372 SkiaFontConfigSetImplementation( | 371 SkiaFontConfigSetImplementation( |
373 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); | 372 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); |
374 | 373 |
375 const char* const sandbox_fd_string = getenv(kSUIDSandboxVar); | 374 if (setuid_sandbox->IsSuidSandboxChild()) { |
376 if (sandbox_fd_string) { | |
377 char* endptr; | |
378 // Use the SUID sandbox. This still allows the seccomp sandbox to | 375 // Use the SUID sandbox. This still allows the seccomp sandbox to |
379 // be enabled by the process later. | 376 // be enabled by the process later. |
380 *using_suid_sandbox = true; | 377 *using_suid_sandbox = true; |
381 | 378 |
382 // Check if the SUID sandbox provides the correct API version. | 379 if (!setuid_sandbox->IsSuidSandboxUpToDate()) { |
383 const char* const sandbox_api_string = | |
384 getenv(base::kSandboxEnvironmentApiProvides); | |
385 // Assume API version 0 if no environment was found | |
386 long sandbox_api_num = 0; | |
387 if (sandbox_api_string) { | |
388 errno = 0; | |
389 sandbox_api_num = strtol(sandbox_api_string, &endptr, 10); | |
390 if (errno || *endptr) { | |
391 return false; | |
392 } | |
393 } | |
394 | |
395 if (sandbox_api_num != base::kSUIDSandboxApiNumber) { | |
396 LOG(WARNING) << "You are using a wrong version of the setuid binary!\n" | 380 LOG(WARNING) << "You are using a wrong version of the setuid binary!\n" |
397 "Please read " | 381 "Please read " |
398 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." | 382 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." |
399 "\n\n"; | 383 "\n\n"; |
400 } | 384 } |
401 | 385 |
402 // Get the file descriptor to signal the chroot helper. | 386 if (!setuid_sandbox->ChrootMe()) |
403 errno = 0; | |
404 const long fd_long = strtol(sandbox_fd_string, &endptr, 10); | |
405 if (errno || !*sandbox_fd_string || *endptr || fd_long < 0 || | |
406 fd_long > INT_MAX) { | |
407 return false; | 387 return false; |
408 } | |
409 const int fd = fd_long; | |
410 | |
411 static const char kMsgChrootMe = 'C'; | |
412 static const char kMsgChrootSuccessful = 'O'; | |
413 | |
414 if (HANDLE_EINTR(write(fd, &kMsgChrootMe, 1)) != 1) { | |
415 LOG(ERROR) << "Failed to write to chroot pipe: " << errno; | |
416 return false; | |
417 } | |
418 | |
419 // We need to reap the chroot helper process in any event: | |
420 wait(NULL); | |
421 | |
422 char reply; | |
423 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { | |
424 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; | |
425 return false; | |
426 } | |
427 | |
428 if (reply != kMsgChrootSuccessful) { | |
429 LOG(ERROR) << "Error code reply from chroot helper"; | |
430 return false; | |
431 } | |
432 | 388 |
433 if (getpid() == 1) { | 389 if (getpid() == 1) { |
434 // The setuid sandbox has created a new PID namespace and we need | 390 // The setuid sandbox has created a new PID namespace and we need |
435 // to assume the role of init. | 391 // to assume the role of init. |
436 if (!CreateInitProcessReaper()) { | 392 if (!CreateInitProcessReaper()) { |
437 LOG(ERROR) << "Error creating an init process to reap zombies"; | 393 LOG(ERROR) << "Error creating an init process to reap zombies"; |
438 return false; | 394 return false; |
439 } | 395 } |
440 *has_started_new_init = true; | 396 *has_started_new_init = true; |
441 } | 397 } |
(...skipping 24 matching lines...) Expand all Loading... |
466 return false; | 422 return false; |
467 } | 423 } |
468 } | 424 } |
469 #endif | 425 #endif |
470 } | 426 } |
471 | 427 |
472 return true; | 428 return true; |
473 } | 429 } |
474 #else // CHROMIUM_SELINUX | 430 #else // CHROMIUM_SELINUX |
475 | 431 |
476 static bool EnterSandbox(bool* using_suid_sandbox, bool* has_started_new_init) { | 432 static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, |
| 433 bool* using_suid_sandbox, bool* has_started_new_init) { |
477 *using_suid_sandbox = false; | 434 *using_suid_sandbox = false; |
478 *has_started_new_init = false; | 435 *has_started_new_init = false; |
479 | 436 |
| 437 if (!setuid_sandbox) |
| 438 return false; |
| 439 |
480 PreSandboxInit(); | 440 PreSandboxInit(); |
481 SkiaFontConfigSetImplementation( | 441 SkiaFontConfigSetImplementation( |
482 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); | 442 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); |
483 return true; | 443 return true; |
484 } | 444 } |
485 | 445 |
486 #endif // CHROMIUM_SELINUX | 446 #endif // CHROMIUM_SELINUX |
487 | 447 |
488 bool ZygoteMain(const MainFunctionParams& params, | 448 bool ZygoteMain(const MainFunctionParams& params, |
489 ZygoteForkDelegate* forkdelegate) { | 449 ZygoteForkDelegate* forkdelegate) { |
490 #if !defined(CHROMIUM_SELINUX) | 450 #if !defined(CHROMIUM_SELINUX) |
491 g_am_zygote_or_renderer = true; | 451 g_am_zygote_or_renderer = true; |
492 sandbox::InitLibcUrandomOverrides(); | 452 sandbox::InitLibcUrandomOverrides(); |
493 #endif | 453 #endif |
494 | 454 |
495 int proc_fd_for_seccomp = -1; | 455 int proc_fd_for_seccomp = -1; |
496 #if defined(SECCOMP_SANDBOX) | 456 #if defined(SECCOMP_SANDBOX) |
497 if (SeccompSandboxEnabled()) { | 457 if (SeccompSandboxEnabled()) { |
498 // The seccomp sandbox needs access to files in /proc, which might be denied | 458 // The seccomp sandbox needs access to files in /proc, which might be denied |
499 // after one of the other sandboxes have been started. So, obtain a suitable | 459 // after one of the other sandboxes have been started. So, obtain a suitable |
500 // file handle in advance. | 460 // file handle in advance. |
501 proc_fd_for_seccomp = open("/proc", O_DIRECTORY | O_RDONLY); | 461 proc_fd_for_seccomp = open("/proc", O_DIRECTORY | O_RDONLY); |
502 if (proc_fd_for_seccomp < 0) { | 462 if (proc_fd_for_seccomp < 0) { |
503 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " | 463 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " |
504 "sandboxing."; | 464 "sandboxing."; |
505 } | 465 } |
506 } | 466 } |
507 #endif // SECCOMP_SANDBOX | 467 #endif // SECCOMP_SANDBOX |
508 | 468 |
| 469 scoped_ptr<sandbox::SetuidSandboxClient> |
| 470 setuid_sandbox(sandbox::SetuidSandboxClient::Create()); |
| 471 |
| 472 if (setuid_sandbox == NULL) { |
| 473 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; |
| 474 return false; |
| 475 } |
| 476 |
509 if (forkdelegate != NULL) { | 477 if (forkdelegate != NULL) { |
510 VLOG(1) << "ZygoteMain: initializing fork delegate"; | 478 VLOG(1) << "ZygoteMain: initializing fork delegate"; |
511 forkdelegate->Init(getenv(kSUIDSandboxVar) != NULL, | 479 forkdelegate->Init(setuid_sandbox->IsSuidSandboxChild(), |
512 Zygote::kBrowserDescriptor, | 480 Zygote::kBrowserDescriptor, |
513 Zygote::kMagicSandboxIPCDescriptor); | 481 Zygote::kMagicSandboxIPCDescriptor); |
514 } else { | 482 } else { |
515 VLOG(1) << "ZygoteMain: fork delegate is NULL"; | 483 VLOG(1) << "ZygoteMain: fork delegate is NULL"; |
516 } | 484 } |
517 | 485 |
518 // Turn on the SELinux or SUID sandbox. | 486 // Turn on the SELinux or SUID sandbox. |
519 bool using_suid_sandbox = false; | 487 bool using_suid_sandbox = false; |
520 bool has_started_new_init = false; | 488 bool has_started_new_init = false; |
521 if (!EnterSandbox(&using_suid_sandbox, &has_started_new_init)) { | 489 if (!EnterSandbox(setuid_sandbox.get(), |
| 490 &using_suid_sandbox, |
| 491 &has_started_new_init)) { |
522 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " | 492 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " |
523 << errno << ")"; | 493 << errno << ")"; |
524 return false; | 494 return false; |
525 } | 495 } |
526 | 496 |
527 int sandbox_flags = 0; | 497 int sandbox_flags = 0; |
528 if (using_suid_sandbox) { | 498 if (using_suid_sandbox) { |
529 sandbox_flags |= kSandboxLinuxSUID; | 499 sandbox_flags |= kSandboxLinuxSUID; |
530 if (getenv("SBX_PID_NS")) | 500 if (setuid_sandbox->IsInNewPIDNamespace()) |
531 sandbox_flags |= kSandboxLinuxPIDNS; | 501 sandbox_flags |= kSandboxLinuxPIDNS; |
532 if (getenv("SBX_NET_NS")) | 502 if (setuid_sandbox->IsInNewNETNamespace()) |
533 sandbox_flags |= kSandboxLinuxNetNS; | 503 sandbox_flags |= kSandboxLinuxNetNS; |
534 } | 504 } |
535 | 505 |
536 if ((sandbox_flags & kSandboxLinuxPIDNS) && !has_started_new_init) { | 506 if ((sandbox_flags & kSandboxLinuxPIDNS) && !has_started_new_init) { |
537 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " | 507 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " |
538 "is not the init process. Please, make sure the SUID " | 508 "is not the init process. Please, make sure the SUID " |
539 "binary is up to date."; | 509 "binary is up to date."; |
540 } | 510 } |
541 | 511 |
542 #if defined(SECCOMP_SANDBOX) | 512 #if defined(SECCOMP_SANDBOX) |
(...skipping 17 matching lines...) Expand all Loading... |
560 } | 530 } |
561 } | 531 } |
562 #endif // SECCOMP_SANDBOX | 532 #endif // SECCOMP_SANDBOX |
563 | 533 |
564 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); | 534 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); |
565 // This function call can return multiple times, once per fork(). | 535 // This function call can return multiple times, once per fork(). |
566 return zygote.ProcessRequests(); | 536 return zygote.ProcessRequests(); |
567 } | 537 } |
568 | 538 |
569 } // namespace content | 539 } // namespace content |
OLD | NEW |