| Index: content/zygote/zygote_main_linux.cc
|
| diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
|
| index 8f89580d42f6ed7a97b86e0e8651acf0905675a5..d1bd8cc076f44cef02f51a3033507e49a43b722e 100644
|
| --- a/content/zygote/zygote_main_linux.cc
|
| +++ b/content/zygote/zygote_main_linux.cc
|
| @@ -39,8 +39,10 @@
|
| #include "content/public/common/zygote_fork_delegate_linux.h"
|
| #include "content/zygote/zygote_linux.h"
|
| #include "crypto/nss_util.h"
|
| +#include "sandbox/linux/services/credentials.h"
|
| #include "sandbox/linux/services/init_process_reaper.h"
|
| #include "sandbox/linux/services/libc_urandom_override.h"
|
| +#include "sandbox/linux/services/namespace_sandbox.h"
|
| #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
|
| #include "third_party/icu/source/i18n/unicode/timezone.h"
|
| #include "third_party/skia/include/ports/SkFontConfigInterface.h"
|
| @@ -399,6 +401,24 @@ static bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback) {
|
| return true;
|
| }
|
|
|
| +static bool MaybeSetProcessNonDumpable() {
|
| + const base::CommandLine& command_line =
|
| + *base::CommandLine::ForCurrentProcess();
|
| + if (command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
|
| + // If sandbox debugging is allowed, install a handler for sandbox-related
|
| + // crash testing.
|
| + InstallSandboxCrashTestHandler();
|
| + return true;
|
| + }
|
| +
|
| + if (prctl(PR_SET_DUMPABLE, 0) != 0) {
|
| + PLOG(ERROR) << "Failed to set non-dumpable flag";
|
| + return false;
|
| + }
|
| +
|
| + return prctl(PR_GET_DUMPABLE) == 0;
|
| +}
|
| +
|
| // Enter the setuid sandbox. This requires the current process to have been
|
| // created through the setuid sandbox.
|
| static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
|
| @@ -433,41 +453,27 @@ static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
|
| CHECK(CreateInitProcessReaper(post_fork_parent_callback));
|
| }
|
|
|
| -#if !defined(OS_OPENBSD)
|
| - // Previously, we required that the binary be non-readable. This causes the
|
| - // kernel to mark the process as non-dumpable at startup. The thinking was
|
| - // that, although we were putting the renderers into a PID namespace (with
|
| - // the SUID sandbox), they would nonetheless be in the /same/ PID
|
| - // namespace. So they could ptrace each other unless they were non-dumpable.
|
| - //
|
| - // If the binary was readable, then there would be a window between process
|
| - // startup and the point where we set the non-dumpable flag in which a
|
| - // compromised renderer could ptrace attach.
|
| - //
|
| - // However, now that we have a zygote model, only the (trusted) zygote
|
| - // exists at this point and we can set the non-dumpable flag which is
|
| - // inherited by all our renderer children.
|
| - //
|
| - // Note: a non-dumpable process can't be debugged. To debug sandbox-related
|
| - // issues, one can specify --allow-sandbox-debugging to let the process be
|
| - // dumpable.
|
| - const base::CommandLine& command_line =
|
| - *base::CommandLine::ForCurrentProcess();
|
| - if (!command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
|
| - prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
|
| - if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
|
| - LOG(ERROR) << "Failed to set non-dumpable flag";
|
| - return false;
|
| - }
|
| - } else {
|
| - // If sandbox debugging is allowed, install a handler for sandbox-related
|
| - // crash testing.
|
| - InstallSandboxCrashTestHandler();
|
| + CHECK(MaybeSetProcessNonDumpable());
|
| + return true;
|
| +}
|
| +
|
| +static void EnterNamespaceSandbox(base::Closure* post_fork_parent_callback) {
|
| + pid_t pid = getpid();
|
| + if (sandbox::NamespaceSandbox::InNewPidNamespace()) {
|
| + CHECK_EQ(1, pid);
|
| }
|
|
|
| -#endif
|
| + CHECK(sandbox::Credentials::MoveToNewUserNS());
|
| + CHECK(sandbox::Credentials::DropFileSystemAccess());
|
| + CHECK(sandbox::Credentials::DropAllCapabilities());
|
|
|
| - return true;
|
| + // This needs to happen after moving to a new user NS, since doing so involves
|
| + // writing the UID/GID map.
|
| + CHECK(MaybeSetProcessNonDumpable());
|
| +
|
| + if (pid == 1) {
|
| + CHECK(CreateInitProcessReaper(post_fork_parent_callback));
|
| + }
|
| }
|
|
|
| #if defined(ADDRESS_SANITIZER)
|
| @@ -526,10 +532,8 @@ static pid_t ForkSanitizerCoverageHelper(
|
|
|
| #endif // defined(ADDRESS_SANITIZER)
|
|
|
| -// If |is_suid_sandbox_child|, then make sure that the setuid sandbox is
|
| -// engaged.
|
| static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox,
|
| - bool is_suid_sandbox_child,
|
| + const bool using_layer1_sandbox,
|
| base::Closure* post_fork_parent_callback) {
|
| DCHECK(linux_sandbox);
|
|
|
| @@ -542,10 +546,13 @@ static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox,
|
|
|
| sandbox::SetuidSandboxClient* setuid_sandbox =
|
| linux_sandbox->setuid_sandbox_client();
|
| -
|
| - if (is_suid_sandbox_child) {
|
| + if (setuid_sandbox->IsSuidSandboxChild()) {
|
| CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback))
|
| << "Failed to enter setuid sandbox";
|
| + } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
|
| + EnterNamespaceSandbox(post_fork_parent_callback);
|
| + } else {
|
| + CHECK(!using_layer1_sandbox);
|
| }
|
| }
|
|
|
| @@ -583,9 +590,12 @@ bool ZygoteMain(const MainFunctionParams& params,
|
| linux_sandbox->PreinitializeSandbox();
|
| }
|
|
|
| - const bool must_enable_setuid_sandbox =
|
| + const bool using_setuid_sandbox =
|
| linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild();
|
| - if (must_enable_setuid_sandbox) {
|
| + const bool using_namespace_sandbox =
|
| + sandbox::NamespaceSandbox::InNewUserNamespace();
|
| +
|
| + if (using_setuid_sandbox) {
|
| linux_sandbox->setuid_sandbox_client()->CloseDummyFile();
|
|
|
| // Let the ZygoteHost know we're booting up.
|
| @@ -597,10 +607,10 @@ bool ZygoteMain(const MainFunctionParams& params,
|
|
|
| VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size()
|
| << " fork delegates";
|
| - for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin();
|
| - i != fork_delegates.end();
|
| - ++i) {
|
| - (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox);
|
| + const bool using_layer1_sandbox =
|
| + using_setuid_sandbox || using_namespace_sandbox;
|
| + for (ZygoteForkDelegate* fork_delegate : fork_delegates) {
|
| + fork_delegate->Init(GetSandboxFD(), using_layer1_sandbox);
|
| }
|
|
|
| const std::vector<int> sandbox_fds_to_close_post_fork =
|
| @@ -613,7 +623,7 @@ bool ZygoteMain(const MainFunctionParams& params,
|
| base::Bind(&CloseFds, fds_to_close_post_fork);
|
|
|
| // Turn on the first layer of the sandbox if the configuration warrants it.
|
| - EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox,
|
| + EnterLayerOneSandbox(linux_sandbox, using_layer1_sandbox,
|
| &post_fork_parent_callback);
|
|
|
| // Extra children and file descriptors created that the Zygote must have
|
| @@ -638,7 +648,7 @@ bool ZygoteMain(const MainFunctionParams& params,
|
|
|
| int sandbox_flags = linux_sandbox->GetStatus();
|
| bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID;
|
| - CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged);
|
| + CHECK_EQ(using_setuid_sandbox, setuid_sandbox_engaged);
|
|
|
| Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children,
|
| extra_fds);
|
|
|