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. |
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(); |
@@ -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()) { |
+ 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 |