Commit e7a01ec4 authored by jln@chromium.org's avatar jln@chromium.org

Create a class for seccomp-bpf sandboxing in content.

This adds a SandboxSeccompBpf class to centralize Seccomp BPF sandbox
policies inside of content/

LinuxSandbox is the only user of this class and Linux sandboxing is now fully
unified through LinuxSandbox.

BUG=
NOTRY=true

Review URL: https://chromiumcodereview.appspot.com/10843042

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149738 0039d316-1c4b-4281-b951-d872f2087c98
parent 7fabd76e
...@@ -100,11 +100,13 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) { ...@@ -100,11 +100,13 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
switches::kVModule, switches::kVModule,
switches::kRegisterPepperPlugins, switches::kRegisterPepperPlugins,
switches::kDisableSeccompSandbox, switches::kDisableSeccompSandbox,
switches::kDisableSeccompFilterSandbox,
switches::kEnableSeccompSandbox, switches::kEnableSeccompSandbox,
// Zygote process needs to know what resources to have loaded when it // Zygote process needs to know what resources to have loaded when it
// becomes a renderer process. // becomes a renderer process.
switches::kForceDeviceScaleFactor, switches::kForceDeviceScaleFactor,
switches::kLoad2xResources, switches::kLoad2xResources,
switches::kNoSandbox,
}; };
cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches)); arraysize(kForwardSwitches));
......
This diff is collapsed.
...@@ -8,20 +8,33 @@ ...@@ -8,20 +8,33 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/eintr_wrapper.h" #include "base/eintr_wrapper.h"
#include "base/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/time.h"
#include "content/common/sandbox_linux.h" #include "content/common/sandbox_linux.h"
#include "content/common/seccomp_sandbox.h" #include "content/common/seccomp_sandbox.h"
#include "content/common/sandbox_seccomp_bpf_linux.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_linux.h" #include "content/public/common/sandbox_linux.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h" #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#if defined(SECCOMP_BPF_SANDBOX)
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#endif
namespace { namespace {
void LogSandboxStarted(const std::string& sandbox_name) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
const std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
const std::string activated_sandbox =
"Activated " + sandbox_name + " sandbox for process type: " +
process_type + ".";
#if defined(OS_CHROMEOS)
LOG(WARNING) << activated_sandbox;
#else
VLOG(1) << activated_sandbox;
#endif
}
// Implement the command line enabling logic for seccomp-legacy. // Implement the command line enabling logic for seccomp-legacy.
bool IsSeccompLegacyDesired() { bool IsSeccompLegacyDesired() {
#if defined(SECCOMP_SANDBOX) #if defined(SECCOMP_SANDBOX)
...@@ -38,6 +51,17 @@ bool IsSeccompLegacyDesired() { ...@@ -38,6 +51,17 @@ bool IsSeccompLegacyDesired() {
return false; return false;
} }
// Our "policy" on whether or not to enable seccomp-legacy. Only renderers are
// supported.
bool ShouldEnableSeccompLegacy(const std::string& process_type) {
if (IsSeccompLegacyDesired() &&
process_type == switches::kRendererProcess) {
return true;
} else {
return false;
}
}
} // namespace } // namespace
namespace content { namespace content {
...@@ -46,6 +70,7 @@ LinuxSandbox::LinuxSandbox() ...@@ -46,6 +70,7 @@ LinuxSandbox::LinuxSandbox()
: proc_fd_(-1), : proc_fd_(-1),
pre_initialized_(false), pre_initialized_(false),
seccomp_legacy_supported_(false), seccomp_legacy_supported_(false),
seccomp_bpf_supported_(false),
setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
if (setuid_sandbox_client_ == NULL) { if (setuid_sandbox_client_ == NULL) {
LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; LOG(FATAL) << "Failed to instantiate the setuid sandbox client.";
...@@ -64,6 +89,7 @@ LinuxSandbox* LinuxSandbox::GetInstance() { ...@@ -64,6 +89,7 @@ LinuxSandbox* LinuxSandbox::GetInstance() {
void LinuxSandbox::PreinitializeSandboxBegin() { void LinuxSandbox::PreinitializeSandboxBegin() {
CHECK(!pre_initialized_); CHECK(!pre_initialized_);
seccomp_legacy_supported_ = false; seccomp_legacy_supported_ = false;
seccomp_bpf_supported_ = false;
#if defined(SECCOMP_SANDBOX) #if defined(SECCOMP_SANDBOX)
if (IsSeccompLegacyDesired()) { if (IsSeccompLegacyDesired()) {
proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
...@@ -84,15 +110,16 @@ void LinuxSandbox::PreinitializeSandboxBegin() { ...@@ -84,15 +110,16 @@ void LinuxSandbox::PreinitializeSandboxBegin() {
} }
} }
#endif // SECCOMP_SANDBOX #endif // SECCOMP_SANDBOX
#if defined(SECCOMP_BPF_SANDBOX)
// Similarly, we "pre-warm" the code that detects supports for seccomp BPF. // 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 // TODO(jln): Use proc_fd_ here too once we're comfortable it does not create
// an additional security risk. // an additional security risk.
if (playground2::Sandbox::supportsSeccompSandbox(-1) != if (SandboxSeccompBpf::IsSeccompBpfDesired()) {
playground2::Sandbox::STATUS_AVAILABLE) { if (!SandboxSeccompBpf::SupportsSandbox()) {
VLOG(1) << "Lacking support for seccomp-bpf sandbox."; VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
} else {
seccomp_bpf_supported_ = true;
}
} }
#endif // SECCOMP_BPF_SANDBOX
pre_initialized_ = true; pre_initialized_ = true;
} }
...@@ -119,7 +146,7 @@ void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) { ...@@ -119,7 +146,7 @@ void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) {
PreinitializeSandboxFinish(process_type); PreinitializeSandboxFinish(process_type);
} }
int LinuxSandbox::GetStatus() { int LinuxSandbox::GetStatus() const {
CHECK(pre_initialized_); CHECK(pre_initialized_);
int sandbox_flags = 0; int sandbox_flags = 0;
if (setuid_sandbox_client_->IsSandboxed()) { if (setuid_sandbox_client_->IsSandboxed()) {
...@@ -129,12 +156,28 @@ int LinuxSandbox::GetStatus() { ...@@ -129,12 +156,28 @@ int LinuxSandbox::GetStatus() {
if (setuid_sandbox_client_->IsInNewNETNamespace()) if (setuid_sandbox_client_->IsInNewNETNamespace())
sandbox_flags |= kSandboxLinuxNetNS; sandbox_flags |= kSandboxLinuxNetNS;
} }
if (seccomp_legacy_supported_) { if (seccomp_legacy_supported() &&
ShouldEnableSeccompLegacy(switches::kRendererProcess)) {
// We report whether the sandbox will be activated when renderers go
// through sandbox initialization.
sandbox_flags |= kSandboxLinuxSeccomp; sandbox_flags |= kSandboxLinuxSeccomp;
} }
return sandbox_flags; return sandbox_flags;
} }
bool LinuxSandbox::IsSingleThreaded() const {
// TODO(jln): re-implement this properly and use our proc_fd_ if available.
// Possibly racy, but it's ok because this is more of a debug check to catch
// new threaded situations arising during development.
int num_threads = file_util::CountFilesCreatedAfter(
FilePath("/proc/self/task"),
base::Time::UnixEpoch());
// We pass the test if we don't know ( == 0), because the setuid sandbox
// will prevent /proc access in some contexts.
return num_threads == 1 || num_threads == 0;
}
sandbox::SetuidSandboxClient* sandbox::SetuidSandboxClient*
LinuxSandbox::setuid_sandbox_client() const { LinuxSandbox::setuid_sandbox_client() const {
return setuid_sandbox_client_.get(); return setuid_sandbox_client_.get();
...@@ -144,13 +187,14 @@ sandbox::SetuidSandboxClient* ...@@ -144,13 +187,14 @@ sandbox::SetuidSandboxClient*
bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) {
if (!pre_initialized_) if (!pre_initialized_)
PreinitializeSandbox(process_type); PreinitializeSandbox(process_type);
if (ShouldEnableSeccompLegacy(process_type)) { if (seccomp_legacy_supported() && ShouldEnableSeccompLegacy(process_type)) {
// SupportsSeccompSandbox() returns a cached result, as we already // SupportsSeccompSandbox() returns a cached result, as we already
// called it earlier in the PreinitializeSandbox(). Thus, it is OK for us // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us
// to not pass in a file descriptor for "/proc". // to not pass in a file descriptor for "/proc".
#if defined(SECCOMP_SANDBOX) #if defined(SECCOMP_SANDBOX)
if (SupportsSeccompSandbox(-1)) { if (SupportsSeccompSandbox(-1)) {
StartSeccompSandbox(); StartSeccompSandbox();
LogSandboxStarted("seccomp-legacy");
return true; return true;
} }
#endif #endif
...@@ -158,26 +202,28 @@ bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { ...@@ -158,26 +202,28 @@ bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) {
return false; return false;
} }
// For seccomp-bpf, we will use the seccomp-bpf policy class. // For seccomp-bpf, we use the SandboxSeccompBpf class.
// TODO(jln): implement this.
bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) { bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) {
if (!pre_initialized_)
PreinitializeSandbox(process_type);
bool started_bpf_sandbox = false;
if (seccomp_bpf_supported())
started_bpf_sandbox = SandboxSeccompBpf::StartSandbox(process_type);
if (started_bpf_sandbox)
LogSandboxStarted("seccomp-bpf");
return started_bpf_sandbox;
}
bool LinuxSandbox::seccomp_legacy_supported() const {
CHECK(pre_initialized_); CHECK(pre_initialized_);
NOTREACHED(); return seccomp_legacy_supported_;
return false;
} }
// Our "policy" on whether or not to enable seccomp-legacy. Only renderers are bool LinuxSandbox::seccomp_bpf_supported() const {
// supported.
bool LinuxSandbox::ShouldEnableSeccompLegacy(
const std::string& process_type) {
CHECK(pre_initialized_); CHECK(pre_initialized_);
if (IsSeccompLegacyDesired() && return seccomp_bpf_supported_;
seccomp_legacy_supported_ &&
process_type == switches::kRendererProcess) {
return true;
} else {
return false;
}
} }
} // namespace content } // namespace content
......
...@@ -5,14 +5,12 @@ ...@@ -5,14 +5,12 @@
#ifndef CONTENT_COMMON_SANDBOX_LINUX_H_ #ifndef CONTENT_COMMON_SANDBOX_LINUX_H_
#define CONTENT_COMMON_SANDBOX_LINUX_H_ #define CONTENT_COMMON_SANDBOX_LINUX_H_
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "content/public/common/sandbox_linux.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; template <typename T> struct DefaultSingletonTraits;
namespace sandbox { class SetuidSandboxClient; } namespace sandbox { class SetuidSandboxClient; }
...@@ -60,7 +58,9 @@ class LinuxSandbox { ...@@ -60,7 +58,9 @@ class LinuxSandbox {
// Since we need to provide the status before the sandboxes are actually // Since we need to provide the status before the sandboxes are actually
// started, this returns what will actually happen once the various Start* // started, this returns what will actually happen once the various Start*
// functions are called from inside a renderer. // functions are called from inside a renderer.
int GetStatus(); int GetStatus() const;
// Is the current process single threaded ?
bool IsSingleThreaded() const;
// Simple accessor for our instance of the setuid sandbox. Will never return // Simple accessor for our instance of the setuid sandbox. Will never return
// NULL. // NULL.
...@@ -71,21 +71,24 @@ class LinuxSandbox { ...@@ -71,21 +71,24 @@ class LinuxSandbox {
// Check the policy and eventually start the seccomp-legacy sandbox. // Check the policy and eventually start the seccomp-legacy sandbox.
bool StartSeccompLegacy(const std::string& process_type); bool StartSeccompLegacy(const std::string& process_type);
// Check the policy and eventually start the seccomp-bpf sandbox. // Check the policy and eventually start the seccomp-bpf sandbox.
// TODO(jln): not implemented at the moment.
bool StartSeccompBpf(const std::string& process_type); bool StartSeccompBpf(const std::string& process_type);
private: private:
friend struct DefaultSingletonTraits<LinuxSandbox>; friend struct DefaultSingletonTraits<LinuxSandbox>;
bool ShouldEnableSeccompLegacy(const std::string& process_type);
// We must have been pre_initialized_ before using either of these.
bool seccomp_legacy_supported() const;
bool seccomp_bpf_supported() const;
int proc_fd_; int proc_fd_;
// Have we been through PreinitializeSandbox or PreinitializeSandboxBegin ? // Have we been through PreinitializeSandbox or PreinitializeSandboxBegin ?
bool pre_initialized_; bool pre_initialized_;
bool seccomp_legacy_supported_; // Accurate if pre_initialized_. bool seccomp_legacy_supported_; // Accurate if pre_initialized_.
bool seccomp_bpf_supported_; // Accurate if pre_initialized_.
scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_; scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_;
LinuxSandbox();
~LinuxSandbox(); ~LinuxSandbox();
DISALLOW_COPY_AND_ASSIGN(LinuxSandbox); DISALLOW_IMPLICIT_CONSTRUCTORS(LinuxSandbox);
}; };
} // namespace content } // namespace content
......
This diff is collapsed.
// 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_SECCOMP_BPF_LINUX_H_
#define CONTENT_COMMON_SANDBOX_SECCOMP_BPF_LINUX_H_
#include "base/basictypes.h"
namespace content {
class SandboxSeccompBpf {
public:
// Is the sandbox globally enabled, can anything use it at all ?
static bool IsSeccompBpfDesired();
// Should the sandbox be enabled for process_type ?
static bool ShouldEnableSeccompBpf(const std::string& process_type);
// Check if the kernel supports this sandbox. It's useful to "prewarm"
// this, part of the result will be cached.
static bool SupportsSandbox();
// Start the sandbox and apply the policy for process_type.
static bool StartSandbox(const std::string& process_type);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxSeccompBpf);
};
} // namespace content
#endif // CONTENT_COMMON_SANDBOX_SECCOMP_BPF_LINUX_H_
...@@ -324,6 +324,8 @@ ...@@ -324,6 +324,8 @@
'common/sandbox_linux.cc', 'common/sandbox_linux.cc',
'common/sandbox_policy.cc', 'common/sandbox_policy.cc',
'common/sandbox_policy.h', 'common/sandbox_policy.h',
'common/sandbox_seccomp_bpf_linux.cc',
'common/sandbox_seccomp_bpf_linux.h',
'common/savable_url_schemes.cc', 'common/savable_url_schemes.cc',
'common/savable_url_schemes.h', 'common/savable_url_schemes.h',
'common/set_process_title.cc', 'common/set_process_title.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment