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

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

Issue 10807059: Refactor the setuid sandbox client code to its own class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address reviewer's comments and other minor nits. Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/zygote_host_impl_linux.cc ('k') | sandbox/linux/sandbox_linux.gypi » ('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 <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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/zygote_host_impl_linux.cc ('k') | sandbox/linux/sandbox_linux.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698