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) {
switches::kVModule,
switches::kRegisterPepperPlugins,
switches::kDisableSeccompSandbox,
switches::kDisableSeccompFilterSandbox,
switches::kEnableSeccompSandbox,
// Zygote process needs to know what resources to have loaded when it
// becomes a renderer process.
switches::kForceDeviceScaleFactor,
switches::kLoad2xResources,
switches::kNoSandbox,
};
cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
......
This diff is collapsed.
......@@ -8,20 +8,33 @@
#include "base/command_line.h"
#include "base/eintr_wrapper.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/time.h"
#include "content/common/sandbox_linux.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/sandbox_linux.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 {
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.
bool IsSeccompLegacyDesired() {
#if defined(SECCOMP_SANDBOX)
......@@ -38,6 +51,17 @@ bool IsSeccompLegacyDesired() {
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 content {
......@@ -46,6 +70,7 @@ LinuxSandbox::LinuxSandbox()
: proc_fd_(-1),
pre_initialized_(false),
seccomp_legacy_supported_(false),
seccomp_bpf_supported_(false),
setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
if (setuid_sandbox_client_ == NULL) {
LOG(FATAL) << "Failed to instantiate the setuid sandbox client.";
......@@ -64,6 +89,7 @@ LinuxSandbox* LinuxSandbox::GetInstance() {
void LinuxSandbox::PreinitializeSandboxBegin() {
CHECK(!pre_initialized_);
seccomp_legacy_supported_ = false;
seccomp_bpf_supported_ = false;
#if defined(SECCOMP_SANDBOX)
if (IsSeccompLegacyDesired()) {
proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
......@@ -84,15 +110,16 @@ void LinuxSandbox::PreinitializeSandboxBegin() {
}
}
#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.";
if (SandboxSeccompBpf::IsSeccompBpfDesired()) {
if (!SandboxSeccompBpf::SupportsSandbox()) {
VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
} else {
seccomp_bpf_supported_ = true;
}
}
#endif // SECCOMP_BPF_SANDBOX
pre_initialized_ = true;
}
......@@ -119,7 +146,7 @@ void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) {
PreinitializeSandboxFinish(process_type);
}
int LinuxSandbox::GetStatus() {
int LinuxSandbox::GetStatus() const {
CHECK(pre_initialized_);
int sandbox_flags = 0;
if (setuid_sandbox_client_->IsSandboxed()) {
......@@ -129,12 +156,28 @@ int LinuxSandbox::GetStatus() {
if (setuid_sandbox_client_->IsInNewNETNamespace())
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;
}
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*
LinuxSandbox::setuid_sandbox_client() const {
return setuid_sandbox_client_.get();
......@@ -144,13 +187,14 @@ sandbox::SetuidSandboxClient*
bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) {
if (!pre_initialized_)
PreinitializeSandbox(process_type);
if (ShouldEnableSeccompLegacy(process_type)) {
if (seccomp_legacy_supported() && 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();
LogSandboxStarted("seccomp-legacy");
return true;
}
#endif
......@@ -158,26 +202,28 @@ bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) {
return false;
}
// For seccomp-bpf, we will use the seccomp-bpf policy class.
// TODO(jln): implement this.
// For seccomp-bpf, we use the SandboxSeccompBpf class.
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_);
NOTREACHED();
return false;
return seccomp_legacy_supported_;
}
// Our "policy" on whether or not to enable seccomp-legacy. Only renderers are
// supported.
bool LinuxSandbox::ShouldEnableSeccompLegacy(
const std::string& process_type) {
bool LinuxSandbox::seccomp_bpf_supported() const {
CHECK(pre_initialized_);
if (IsSeccompLegacyDesired() &&
seccomp_legacy_supported_ &&
process_type == switches::kRendererProcess) {
return true;
} else {
return false;
}
return seccomp_bpf_supported_;
}
} // namespace content
......
......@@ -5,14 +5,12 @@
#ifndef CONTENT_COMMON_SANDBOX_LINUX_H_
#define CONTENT_COMMON_SANDBOX_LINUX_H_
#include <string>
#include "base/basictypes.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; }
......@@ -60,7 +58,9 @@ class LinuxSandbox {
// 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();
int GetStatus() const;
// Is the current process single threaded ?
bool IsSingleThreaded() const;
// Simple accessor for our instance of the setuid sandbox. Will never return
// NULL.
......@@ -71,21 +71,24 @@ class LinuxSandbox {
// 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);
// We must have been pre_initialized_ before using either of these.
bool seccomp_legacy_supported() const;
bool seccomp_bpf_supported() const;
int proc_fd_;
// Have we been through PreinitializeSandbox or PreinitializeSandboxBegin ?
bool 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_;
LinuxSandbox();
~LinuxSandbox();
DISALLOW_COPY_AND_ASSIGN(LinuxSandbox);
DISALLOW_IMPLICIT_CONSTRUCTORS(LinuxSandbox);
};
} // 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 @@
'common/sandbox_linux.cc',
'common/sandbox_policy.cc',
'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.h',
'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