diff options
author | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-02 20:38:04 +0000 |
---|---|---|
committer | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-02 20:38:04 +0000 |
commit | 3c52f8ede1c294f704fdcb162c7a02fb4eb7e7f1 (patch) | |
tree | f640e2b6c6112d799d35bcdd8d987132813418ea | |
parent | a00ca09cd8f799f984f2856aaeac3308dc948071 (diff) | |
download | chromium_src-3c52f8ede1c294f704fdcb162c7a02fb4eb7e7f1.zip chromium_src-3c52f8ede1c294f704fdcb162c7a02fb4eb7e7f1.tar.gz chromium_src-3c52f8ede1c294f704fdcb162c7a02fb4eb7e7f1.tar.bz2 |
Create a LinuxSandbox class.
The LinuxSandbox class aims to become the central place for Linux
sandboxing inside content/.
For now, this refactors mostly code from the Zygote.
BUG=
NOTRY=true
Review URL: https://chromiumcodereview.appspot.com/10826093
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149692 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/render_sandbox_host_linux.cc | 3 | ||||
-rw-r--r-- | content/common/OWNERS | 2 | ||||
-rw-r--r-- | content/common/child_process_sandbox_support_impl_linux.cc | 2 | ||||
-rw-r--r-- | content/common/child_process_sandbox_support_impl_shm_linux.cc | 4 | ||||
-rw-r--r-- | content/common/sandbox_init_linux.cc | 20 | ||||
-rw-r--r-- | content/common/sandbox_linux.cc | 181 | ||||
-rw-r--r-- | content/common/sandbox_linux.h | 94 | ||||
-rw-r--r-- | content/common/sandbox_methods_linux.h | 24 | ||||
-rw-r--r-- | content/common/seccomp_sandbox.h | 24 | ||||
-rw-r--r-- | content/content_common.gypi | 3 | ||||
-rw-r--r-- | content/public/common/sandbox_linux.h | 10 | ||||
-rw-r--r-- | content/zygote/zygote_linux.cc | 22 | ||||
-rw-r--r-- | content/zygote/zygote_linux.h | 12 | ||||
-rw-r--r-- | content/zygote/zygote_main_linux.cc | 69 | ||||
-rw-r--r-- | sandbox/linux/suid/client/setuid_sandbox_client.cc | 13 | ||||
-rw-r--r-- | sandbox/linux/suid/client/setuid_sandbox_client.h | 6 | ||||
-rw-r--r-- | sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc | 3 |
17 files changed, 330 insertions, 162 deletions
diff --git a/content/browser/renderer_host/render_sandbox_host_linux.cc b/content/browser/renderer_host/render_sandbox_host_linux.cc index 2ee8c6b..1ef8e71 100644 --- a/content/browser/renderer_host/render_sandbox_host_linux.cc +++ b/content/browser/renderer_host/render_sandbox_host_linux.cc @@ -28,7 +28,7 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "content/common/font_config_ipc_linux.h" -#include "content/common/sandbox_methods_linux.h" +#include "content/common/sandbox_linux.h" #include "content/common/webkitplatformsupport_impl.h" #include "skia/ext/SkFontHost_fontconfig_direct.h" #include "third_party/npapi/bindings/npapi_extensions.h" @@ -36,6 +36,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontInfo.h" #include "ui/gfx/font_render_params_linux.h" +using content::LinuxSandbox; using WebKit::WebCString; using WebKit::WebFontInfo; using WebKit::WebUChar; diff --git a/content/common/OWNERS b/content/common/OWNERS index f8fc447..4432a1a 100644 --- a/content/common/OWNERS +++ b/content/common/OWNERS @@ -1,4 +1,4 @@ -# For sandbox_init_linux.cc +# For sandbox*_linux.* cevans@chromium.org jln@chromium.org diff --git a/content/common/child_process_sandbox_support_impl_linux.cc b/content/common/child_process_sandbox_support_impl_linux.cc index 9294e7b..8d1b8d5 100644 --- a/content/common/child_process_sandbox_support_impl_linux.cc +++ b/content/common/child_process_sandbox_support_impl_linux.cc @@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/pickle.h" #include "base/posix/unix_domain_socket.h" -#include "content/common/sandbox_methods_linux.h" +#include "content/common/sandbox_linux.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/linux/WebFontFamily.h" #include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontRenderStyle.h" diff --git a/content/common/child_process_sandbox_support_impl_shm_linux.cc b/content/common/child_process_sandbox_support_impl_shm_linux.cc index 4277382..37635df 100644 --- a/content/common/child_process_sandbox_support_impl_shm_linux.cc +++ b/content/common/child_process_sandbox_support_impl_shm_linux.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/pickle.h" #include "base/posix/unix_domain_socket.h" #include "content/common/child_process_sandbox_support_impl_linux.h" -#include "content/common/sandbox_methods_linux.h" +#include "content/common/sandbox_linux.h" namespace content { diff --git a/content/common/sandbox_init_linux.cc b/content/common/sandbox_init_linux.cc index c7066c62..b9cafa2 100644 --- a/content/common/sandbox_init_linux.cc +++ b/content/common/sandbox_init_linux.cc @@ -32,6 +32,7 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/time.h" +#include "content/common/sandbox_linux.h" #include "content/public/common/content_switches.h" #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" @@ -538,23 +539,6 @@ bool InitializeBpfSandbox_x86(const CommandLine& command_line, return true; } -bool InitializeLegacySandbox_x86(const CommandLine& command_line, - const std::string& process_type) { -#if defined(SECCOMP_SANDBOX) - // Start the old seccomp mode 1 (sandbox/linux/seccomp-legacy). - if (process_type == switches::kRendererProcess && SeccompSandboxEnabled()) { - // N.b. SupportsSeccompSandbox() returns a cached result, as we already - // called it earlier in the zygote. Thus, it is OK for us to not pass in - // a file descriptor for "/proc". - if (SupportsSeccompSandbox(-1)) { - StartSeccompSandbox(); - return true; - } - } -#endif - return false; -} - } // anonymous namespace #endif // defined(__i386__) || defined(__x86_64__) @@ -571,7 +555,7 @@ void InitializeSandbox() { // First, try to enable seccomp-legacy. seccomp_legacy_started = - InitializeLegacySandbox_x86(command_line, process_type); + LinuxSandbox::GetInstance()->StartSeccompLegacy(process_type); if (seccomp_legacy_started) LogSandboxStarted("seccomp-legacy", process_type); diff --git a/content/common/sandbox_linux.cc b/content/common/sandbox_linux.cc new file mode 100644 index 0000000..d7d1ed5 --- /dev/null +++ b/content/common/sandbox_linux.cc @@ -0,0 +1,181 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "base/command_line.h" +#include "base/eintr_wrapper.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "content/common/sandbox_linux.h" +#include "content/common/seccomp_sandbox.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/sandbox_linux.h" +#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" +#include "sandbox/linux/suid/client/setuid_sandbox_client.h" + +namespace { + +// Implement the command line enabling logic for seccomp-legacy. +bool IsSeccompLegacyDesired() { +#if defined(SECCOMP_SANDBOX) +#if defined(NDEBUG) + // Off by default; allow turning on with a switch. + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableSeccompSandbox); +#else + // On by default; allow turning off with a switch. + return !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableSeccompSandbox); +#endif // NDEBUG +#endif // SECCOMP_SANDBOX + return false; +} + +} // namespace + +namespace content { + +LinuxSandbox::LinuxSandbox() + : proc_fd_(-1), + pre_initialized_(false), + seccomp_legacy_supported_(false), + setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { + if (setuid_sandbox_client_ == NULL) { + LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; + } +} + +LinuxSandbox::~LinuxSandbox() { +} + +LinuxSandbox* LinuxSandbox::GetInstance() { + LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); + CHECK(instance); + return instance; +} + +void LinuxSandbox::PreinitializeSandboxBegin() { + CHECK(!pre_initialized_); + seccomp_legacy_supported_ = false; +#if defined(SECCOMP_SANDBOX) + if (IsSeccompLegacyDesired()) { + proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); + if (proc_fd_ < 0) { + LOG(ERROR) << "Cannot access \"/proc\". Disabling seccomp-legacy " + "sandboxing."; + // Now is a good time to figure out if we can support seccomp sandboxing + // at all. We will call SupportsSeccompSandbox again later, when actually + // enabling it, but we allow the implementation to cache some information. + // This is the only place where we will log full lack of seccomp-legacy + // support. + } else if (!SupportsSeccompSandbox(proc_fd_)) { + VLOG(1) << "Lacking support for seccomp-legacy sandbox."; + CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0); + proc_fd_ = -1; + } else { + seccomp_legacy_supported_ = true; + } + } +#endif // SECCOMP_SANDBOX +#if defined(SECCOMP_BPF_SANDBOX) + // Similarly, we "pre-warm" the code that detects supports for seccomp BPF. + // TODO(jln): Use proc_fd_ here too once we're comfortable it does not create + // an additional security risk. + if (playground2::Sandbox::supportsSeccompSandbox(-1) != + playground2::Sandbox::STATUS_AVAILABLE) { + VLOG(1) << "Lacking support for seccomp-bpf sandbox."; + } +#endif // SECCOMP_BPF_SANDBOX + pre_initialized_ = true; +} + +// Once we finally know our process type, we can cleanup proc_fd_ +// or pass it to seccomp-legacy. +void LinuxSandbox::PreinitializeSandboxFinish( + const std::string& process_type) { + CHECK(pre_initialized_); + if (proc_fd_ >= 0) { + if (ShouldEnableSeccompLegacy(process_type)) { +#if defined(SECCOMP_SANDBOX) + SeccompSandboxSetProcFd(proc_fd_); +#endif + } else { + DCHECK_GE(proc_fd_, 0); + CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0); + } + proc_fd_ = -1; + } +} + +void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) { + PreinitializeSandboxBegin(); + PreinitializeSandboxFinish(process_type); +} + +int LinuxSandbox::GetStatus() { + CHECK(pre_initialized_); + int sandbox_flags = 0; + if (setuid_sandbox_client_->IsSandboxed()) { + sandbox_flags |= kSandboxLinuxSUID; + if (setuid_sandbox_client_->IsInNewPIDNamespace()) + sandbox_flags |= kSandboxLinuxPIDNS; + if (setuid_sandbox_client_->IsInNewNETNamespace()) + sandbox_flags |= kSandboxLinuxNetNS; + } + if (seccomp_legacy_supported_) { + sandbox_flags |= kSandboxLinuxSeccomp; + } + return sandbox_flags; +} + +sandbox::SetuidSandboxClient* + LinuxSandbox::setuid_sandbox_client() const { + return setuid_sandbox_client_.get(); +} + +// For seccomp-legacy, we implement the policy inline, here. +bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { + if (!pre_initialized_) + PreinitializeSandbox(process_type); + if (ShouldEnableSeccompLegacy(process_type)) { + // SupportsSeccompSandbox() returns a cached result, as we already + // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us + // to not pass in a file descriptor for "/proc". +#if defined(SECCOMP_SANDBOX) + if (SupportsSeccompSandbox(-1)) { + StartSeccompSandbox(); + return true; + } +#endif + } + return false; +} + +// For seccomp-bpf, we will use the seccomp-bpf policy class. +// TODO(jln): implement this. +bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) { + CHECK(pre_initialized_); + NOTREACHED(); + return false; +} + +// Our "policy" on whether or not to enable seccomp-legacy. Only renderers are +// supported. +bool LinuxSandbox::ShouldEnableSeccompLegacy( + const std::string& process_type) { + CHECK(pre_initialized_); + if (IsSeccompLegacyDesired() && + seccomp_legacy_supported_ && + process_type == switches::kRendererProcess) { + return true; + } else { + return false; + } +} + +} // namespace content + diff --git a/content/common/sandbox_linux.h b/content/common/sandbox_linux.h new file mode 100644 index 0000000..8502dfb --- /dev/null +++ b/content/common/sandbox_linux.h @@ -0,0 +1,94 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_SANDBOX_LINUX_H_ +#define CONTENT_COMMON_SANDBOX_LINUX_H_ + +#include "base/memory/scoped_ptr.h" +#include "content/public/common/sandbox_linux.h" + +// TODO(jln) move this somewhere else. +#if defined(__i386__) || defined(__x86_64__) +#define SECCOMP_BPF_SANDBOX +#endif + +template <typename T> struct DefaultSingletonTraits; +namespace sandbox { class SetuidSandboxClient; } + +namespace content { + +// A singleton class to represent and change our sandboxing state for the +// three main Linux sandboxes. +class LinuxSandbox { + public: + // This is a list of sandbox IPC methods which the renderer may send to the + // sandbox host. See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC + // This isn't the full list, values < 32 are reserved for methods called from + // Skia. + enum LinuxSandboxIPCMethods { + METHOD_GET_FONT_FAMILY_FOR_CHARS = 32, + METHOD_LOCALTIME = 33, + METHOD_GET_CHILD_WITH_INODE = 34, + METHOD_GET_STYLE_FOR_STRIKE = 35, + METHOD_MAKE_SHARED_MEMORY_SEGMENT = 36, + METHOD_MATCH_WITH_FALLBACK = 37, + }; + + // Get our singleton instance. + static LinuxSandbox* GetInstance(); + + // Do some initialization that can only be done before any of the sandboxes + // is enabled. + // + // There are two versions of this function. One takes a process_type + // as an argument, the other doesn't. + // It may be necessary to call PreinitializeSandboxBegin before knowing the + // process type (this is for instance the case with the Zygote). + // In that case, it is crucial that PreinitializeSandboxFinish() gets + // called for every child process. + // TODO(markus,jln) we know this is not always done at the moment + // (crbug.com/139877). + void PreinitializeSandbox(const std::string& process_type); + // These should be called together. + void PreinitializeSandboxBegin(); + void PreinitializeSandboxFinish(const std::string& process_type); + + // Returns the Status of the sandbox. Can only be queried if we went through + // PreinitializeSandbox() or PreinitializeSandboxBegin(). This is a bitmask + // and uses the constants defined in "enum LinuxSandboxStatus". + // Since we need to provide the status before the sandboxes are actually + // started, this returns what will actually happen once the various Start* + // functions are called from inside a renderer. + int GetStatus(); + + // Simple accessor for our instance of the setuid sandbox. Will never return + // NULL. + // There is no StartSetuidSandbox(), the SetuidSandboxClient instance should + // be used directly. + sandbox::SetuidSandboxClient* setuid_sandbox_client() const; + + // Check the policy and eventually start the seccomp-legacy sandbox. + bool StartSeccompLegacy(const std::string& process_type); + // Check the policy and eventually start the seccomp-bpf sandbox. + // TODO(jln): not implemented at the moment. + bool StartSeccompBpf(const std::string& process_type); + + private: + friend struct DefaultSingletonTraits<LinuxSandbox>; + bool ShouldEnableSeccompLegacy(const std::string& process_type); + + int proc_fd_; + // Have we been through PreinitializeSandbox or PreinitializeSandboxBegin ? + bool pre_initialized_; + bool seccomp_legacy_supported_; // Accurate if pre_initialized_. + scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_; + LinuxSandbox(); + ~LinuxSandbox(); + DISALLOW_COPY_AND_ASSIGN(LinuxSandbox); +}; + +} // namespace content + +#endif // CONTENT_COMMON_SANDBOX_LINUX_H_ + diff --git a/content/common/sandbox_methods_linux.h b/content/common/sandbox_methods_linux.h deleted file mode 100644 index 3862b0f..0000000 --- a/content/common/sandbox_methods_linux.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_COMMON_SANDBOX_METHODS_LINUX_H_ -#define CONTENT_COMMON_SANDBOX_METHODS_LINUX_H_ - -// This is a list of sandbox IPC methods which the renderer may send to the -// sandbox host. See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC -// This isn't the full list, values < 32 are reserved for methods called from -// Skia. -class LinuxSandbox { - public: - enum Methods { - METHOD_GET_FONT_FAMILY_FOR_CHARS = 32, - METHOD_LOCALTIME = 33, - METHOD_GET_CHILD_WITH_INODE = 34, - METHOD_GET_STYLE_FOR_STRIKE = 35, - METHOD_MAKE_SHARED_MEMORY_SEGMENT = 36, - METHOD_MATCH_WITH_FALLBACK = 37, - }; -}; - -#endif // CONTENT_COMMON_SANDBOX_METHODS_LINUX_H_ diff --git a/content/common/seccomp_sandbox.h b/content/common/seccomp_sandbox.h index 0c59a11..06cf9f8 100644 --- a/content/common/seccomp_sandbox.h +++ b/content/common/seccomp_sandbox.h @@ -8,14 +8,8 @@ // Seccomp enable/disable logic is centralized here. // - We define SECCOMP_SANDBOX if seccomp is compiled in at all: currently, // on non-views (non-ChromeOS) non-ARM non-Clang Linux only. -// - If we have SECCOMP_SANDBOX, we provide SeccompSandboxEnabled() as -// a run-time test to determine whether to turn on seccomp: -// currently, on by default in debug builds and off by default in -// release. -#include "base/command_line.h" #include "build/build_config.h" -#include "content/public/common/content_switches.h" #if defined(ARCH_CPU_X86_FAMILY) && !defined(CHROMIUM_SELINUX) && \ !defined(OS_CHROMEOS) && !defined(TOOLKIT_VIEWS) && !defined(OS_OPENBSD) @@ -23,22 +17,4 @@ #include "sandbox/linux/seccomp-legacy/sandbox.h" #endif -#if defined(SECCOMP_SANDBOX) -// Return true if seccomp is enabled. -static bool SeccompSandboxEnabled() { - // TODO(evan): turn on for release too once we've flushed out all the bugs, - // allowing us to delete this file entirely and just rely on the "disabled" - // switch. -#ifdef NDEBUG - // Off by default; allow turning on with a switch. - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableSeccompSandbox); -#else - // On by default; allow turning off with a switch. - return !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSeccompSandbox); -#endif // NDEBUG -} -#endif // SECCOMP_SANDBOX - #endif // CONTENT_COMMON_SECCOMP_SANDBOX_H_ diff --git a/content/content_common.gypi b/content/content_common.gypi index 8a468bf..62abb78 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -320,7 +320,8 @@ 'common/sandbox_init_linux.cc', 'common/sandbox_mac.h', 'common/sandbox_mac.mm', - 'common/sandbox_methods_linux.h', + 'common/sandbox_linux.h', + 'common/sandbox_linux.cc', 'common/sandbox_policy.cc', 'common/sandbox_policy.h', 'common/savable_url_schemes.cc', diff --git a/content/public/common/sandbox_linux.h b/content/public/common/sandbox_linux.h index e92632f..12ea20c 100644 --- a/content/public/common/sandbox_linux.h +++ b/content/public/common/sandbox_linux.h @@ -8,18 +8,20 @@ namespace content { // These form a bitmask which describes the conditions of the Linux sandbox. -enum { +// Note: this doesn't strictly give you the current status, it states +// what will be enabled when the relevant processes are initialized. +enum LinuxSandboxStatus { // SUID sandbox active. kSandboxLinuxSUID = 1 << 0, // SUID sandbox is using the PID namespace. kSandboxLinuxPIDNS = 1 << 1, - //SUID sandbox is using the network namespace. + // SUID sandbox is using the network namespace. kSandboxLinuxNetNS = 1 << 2, - // seccomp sandbox active. - kSandboxLinuxSeccomp = 1 << 3 + // seccomp-legacy sandbox active. + kSandboxLinuxSeccomp = 1 << 3, }; } // namespace content diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc index 3fcd996..101ea7f 100644 --- a/content/zygote/zygote_linux.cc +++ b/content/zygote/zygote_linux.cc @@ -25,7 +25,7 @@ #include "base/pickle.h" #include "base/posix/unix_domain_socket.h" #include "content/common/set_process_title.h" -#include "content/common/sandbox_methods_linux.h" +#include "content/common/sandbox_linux.h" #include "content/common/zygote_commands_linux.h" #include "content/public/common/content_descriptors.h" #include "content/public/common/zygote_fork_delegate_linux.h" @@ -68,13 +68,9 @@ void SELinuxTransitionToTypeOrDie(const char* type) { } // namespace Zygote::Zygote(int sandbox_flags, - ZygoteForkDelegate* helper, - int proc_fd_for_seccomp) + ZygoteForkDelegate* helper) : sandbox_flags_(sandbox_flags), helper_(helper), -#if defined(SECCOMP_SANDBOX) - proc_fd_for_seccomp_(proc_fd_for_seccomp), -#endif initial_uma_sample_(0), initial_uma_boundary_value_(0) { if (helper_) { @@ -423,17 +419,9 @@ base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle, uma_boundary_value); if (!child_pid) { // This is the child process. -#if defined(SECCOMP_SANDBOX) - if (proc_fd_for_seccomp_ >= 0) { - if (process_type == switches::kRendererProcess && - SeccompSandboxEnabled()) { - SeccompSandboxSetProcFd(proc_fd_for_seccomp_); - } else { - close(proc_fd_for_seccomp_); - } - proc_fd_for_seccomp_ = -1; - } -#endif + + // At this point, we finally know our process type. + LinuxSandbox::GetInstance()->PreinitializeSandboxFinish(process_type); close(kBrowserDescriptor); // Our socket from the browser. if (UsingSUIDSandbox()) diff --git a/content/zygote/zygote_linux.h b/content/zygote/zygote_linux.h index 859bb37..a093855 100644 --- a/content/zygote/zygote_linux.h +++ b/content/zygote/zygote_linux.h @@ -10,7 +10,6 @@ #include "base/hash_tables.h" #include "base/process.h" -#include "content/common/seccomp_sandbox.h" class Pickle; class PickleIterator; @@ -24,12 +23,8 @@ class ZygoteForkDelegate; // runs it. class Zygote { public: - // The proc_fd_for_seccomp should be a file descriptor to /proc under the - // seccomp sandbox. This is not needed when not using seccomp, and should be - // -1 in those cases. Zygote(int sandbox_flags, - ZygoteForkDelegate* helper, - int proc_fd_for_seccomp); + ZygoteForkDelegate* helper); ~Zygote(); bool ProcessRequests(); @@ -98,11 +93,6 @@ class Zygote { const int sandbox_flags_; ZygoteForkDelegate* helper_; -#if defined(SECCOMP_SANDBOX) - // File descriptor to proc under seccomp, -1 when not using seccomp. - int proc_fd_for_seccomp_; -#endif - // These might be set by helper_->InitialUMA. They supply a UMA enumeration // sample we should report on the first fork. std::string initial_uma_name_; diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc index f9b821b..4cd8105 100644 --- a/content/zygote/zygote_main_linux.cc +++ b/content/zygote/zygote_main_linux.cc @@ -28,8 +28,7 @@ #include "crypto/nss_util.h" #include "content/common/font_config_ipc_linux.h" #include "content/common/pepper_plugin_registry.h" -#include "content/common/sandbox_methods_linux.h" -#include "content/common/seccomp_sandbox.h" +#include "content/common/sandbox_linux.h" #include "content/common/zygote_commands_linux.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -452,27 +451,15 @@ bool ZygoteMain(const MainFunctionParams& params, sandbox::InitLibcUrandomOverrides(); #endif - int proc_fd_for_seccomp = -1; -#if defined(SECCOMP_SANDBOX) - if (SeccompSandboxEnabled()) { - // The seccomp sandbox needs access to files in /proc, which might be denied - // after one of the other sandboxes have been started. So, obtain a suitable - // file handle in advance. - proc_fd_for_seccomp = open("/proc", O_DIRECTORY | O_RDONLY); - if (proc_fd_for_seccomp < 0) { - LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " - "sandboxing."; - } - } -#endif // SECCOMP_SANDBOX - - scoped_ptr<sandbox::SetuidSandboxClient> - setuid_sandbox(sandbox::SetuidSandboxClient::Create()); + LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); + // This will pre-initialize the various sandboxes that need it. + // There need to be a corresponding call to PreinitializeSandboxFinish() + // for each new process, this will be done in the Zygote child, once we know + // our process type. + linux_sandbox->PreinitializeSandboxBegin(); - if (setuid_sandbox == NULL) { - LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; - return false; - } + sandbox::SetuidSandboxClient* setuid_sandbox = + linux_sandbox->setuid_sandbox_client(); if (forkdelegate != NULL) { VLOG(1) << "ZygoteMain: initializing fork delegate"; @@ -486,7 +473,8 @@ bool ZygoteMain(const MainFunctionParams& params, // Turn on the SELinux or SUID sandbox. bool using_suid_sandbox = false; bool has_started_new_init = false; - if (!EnterSandbox(setuid_sandbox.get(), + + if (!EnterSandbox(setuid_sandbox, &using_suid_sandbox, &has_started_new_init)) { LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " @@ -494,44 +482,15 @@ bool ZygoteMain(const MainFunctionParams& params, return false; } - int sandbox_flags = 0; - if (using_suid_sandbox) { - sandbox_flags |= kSandboxLinuxSUID; - if (setuid_sandbox->IsInNewPIDNamespace()) - sandbox_flags |= kSandboxLinuxPIDNS; - if (setuid_sandbox->IsInNewNETNamespace()) - sandbox_flags |= kSandboxLinuxNetNS; - } - - if ((sandbox_flags & kSandboxLinuxPIDNS) && !has_started_new_init) { + if (setuid_sandbox->IsInNewPIDNamespace() && !has_started_new_init) { LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " "is not the init process. Please, make sure the SUID " "binary is up to date."; } -#if defined(SECCOMP_SANDBOX) - // The seccomp sandbox will be turned on when the renderers start. But we can - // already check if sufficient support is available so that we only need to - // print one error message for the entire browser session. - if (proc_fd_for_seccomp >= 0 && SeccompSandboxEnabled()) { - if (!SupportsSeccompSandbox(proc_fd_for_seccomp)) { - // There are a good number of users who cannot use the seccomp sandbox - // (e.g. because their distribution does not enable seccomp mode by - // default). While we would prefer to deny execution in this case, it - // seems more realistic to continue in degraded mode. - LOG(ERROR) << "WARNING! This machine lacks support needed for the " - "Seccomp sandbox. Running renderers with Seccomp " - "sandboxing disabled."; - close(proc_fd_for_seccomp); - proc_fd_for_seccomp = -1; - } else { - VLOG(1) << "Enabling experimental Seccomp sandbox."; - sandbox_flags |= kSandboxLinuxSeccomp; - } - } -#endif // SECCOMP_SANDBOX + int sandbox_flags = linux_sandbox->GetStatus(); - Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); + Zygote zygote(sandbox_flags, forkdelegate); // This function call can return multiple times, once per fork(). return zygote.ProcessRequests(); } diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc index 749d2d0..4f62d09 100644 --- a/sandbox/linux/suid/client/setuid_sandbox_client.cc +++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc @@ -103,8 +103,9 @@ SetuidSandboxClient* SetuidSandboxClient::Create() { return sandbox_client; } -SetuidSandboxClient::SetuidSandboxClient() { - env_ = NULL; +SetuidSandboxClient::SetuidSandboxClient() + : env_(NULL), + sandboxed_(false) { } SetuidSandboxClient::~SetuidSandboxClient() { @@ -142,6 +143,10 @@ bool SetuidSandboxClient::ChrootMe() { LOG(ERROR) << "Error code reply from chroot helper"; return false; } + + // We now consider ourselves "fully sandboxed" as far as the + // setuid sandbox is concerned. + sandboxed_ = true; return true; } @@ -161,6 +166,10 @@ bool SetuidSandboxClient::IsInNewNETNamespace() const { return env_->HasVar(kSandboxNETNSEnvironmentVarName); } +bool SetuidSandboxClient::IsSandboxed() const { + return sandboxed_; +} + void SetuidSandboxClient::SetupLaunchEnvironment() { SaveSUIDUnsafeEnvironmentVariables(env_); SetSandboxAPIEnvironmentVariable(env_); diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h index afbde0a..da77ce0 100644 --- a/sandbox/linux/suid/client/setuid_sandbox_client.h +++ b/sandbox/linux/suid/client/setuid_sandbox_client.h @@ -6,7 +6,8 @@ #define SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_ #include "base/basictypes.h" -#include "base/environment.h" + +namespace base { class Environment; } namespace sandbox { @@ -38,6 +39,8 @@ class SetuidSandboxClient { bool IsInNewPIDNamespace() const; // Did the setuid helper create a new network namespace ? bool IsInNewNETNamespace() const; + // Are we done and fully sandboxed ? + bool IsSandboxed() const; // Set-up the environment. This should be done prior to launching the setuid // helper. @@ -46,6 +49,7 @@ class SetuidSandboxClient { private: // Holds the environment. Will never be NULL. base::Environment* env_; + bool sandboxed_; DISALLOW_IMPLICIT_CONSTRUCTORS(SetuidSandboxClient); }; diff --git a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc index 59b02eb..764ccb1 100644 --- a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc +++ b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc @@ -73,6 +73,9 @@ TEST(SetuidSandboxClient, SandboxedClientAPI) { EXPECT_TRUE(env->SetVar(kSandboxEnvironmentApiProvides, base::IntToString(kSUIDSandboxApiNumber + 1))); EXPECT_FALSE(sandbox_client->IsSuidSandboxUpToDate()); + // We didn't go through the actual sandboxing mechanism as it is + // very hard in a unit test. + EXPECT_FALSE(sandbox_client->IsSandboxed()); } } // namespace sandbox |