Chromium Code Reviews| Index: content/common/sandbox_linux.cc |
| diff --git a/content/common/sandbox_linux.cc b/content/common/sandbox_linux.cc |
| index d7d1ed5607d3755e2a67fc4a801e645a26526a12..8280c7aeb38f4b13963879a679862797b2de1fc8 100644 |
| --- a/content/common/sandbox_linux.cc |
| +++ b/content/common/sandbox_linux.cc |
| @@ -8,17 +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/seccomp-bpf/sandbox_bpf.h" |
| #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
| 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) |
| @@ -35,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 { |
| @@ -43,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."; |
| @@ -61,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); |
| @@ -81,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; |
| } |
| @@ -116,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()) { |
| @@ -126,12 +156,27 @@ int LinuxSandbox::GetStatus() { |
| if (setuid_sandbox_client_->IsInNewNETNamespace()) |
| sandbox_flags |= kSandboxLinuxNetNS; |
| } |
| - if (seccomp_legacy_supported_) { |
| + if (seccomp_legacy_supported()) { |
| + // Note: The current mechanism does not report if the sandbox is activated |
| + // but only if it can be attempted. |
|
piman
2012/08/02 21:40:04
same as previous CL :)
This comment isn't really h
jln (very slow on Chromium)
2012/08/02 22:20:38
I tried to make things more clear but if you don't
piman
2012/08/02 22:24:40
Ok, as you wish. My point is just that users of Ge
|
| 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"), |
|
piman
2012/08/02 21:40:04
nit: indent (should be +4)
Or you can probably br
jln (very slow on Chromium)
2012/08/02 22:20:38
Done.
|
| + 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(); |
| @@ -141,13 +186,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 |
| @@ -155,26 +201,29 @@ 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()) { |
|
piman
2012/08/02 21:40:04
nit: no need for brackets
jln (very slow on Chromium)
2012/08/02 22:20:38
Done.
|
| + 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 |