Chromium Code Reviews| Index: content/common/sandbox_linux.cc |
| diff --git a/content/common/sandbox_linux.cc b/content/common/sandbox_linux.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7b0d270a9bad2ee36e93e02eef05bd0d186629b7 |
| --- /dev/null |
| +++ b/content/common/sandbox_linux.cc |
| @@ -0,0 +1,180 @@ |
| +// 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 { |
| + |
| +inline bool IsSeccompLegacyDesired() { |
|
Markus (顧孟勤)
2012/08/01 22:09:19
Do we ever explicitly use "inline" in our code. So
jln (very slow on Chromium)
2012/08/01 22:21:53
Done.
|
| +#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; |
| +} |
| + |
| +bool ShouldEnableSeccompLegacy(const std::string& process_type) { |
| + if (IsSeccompLegacyDesired() && |
| + process_type == switches::kRendererProcess) { |
| + return true; |
| + } else { |
| + return false; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +namespace content { |
| + |
| +LinuxSandbox::LinuxSandbox() |
| + : proc_fd_(-1), |
| + pre_initialized_(false), |
| + seccomp_legacy_supported_(false), |
| + setuid_sandbox_(NULL) { |
| +} |
| + |
| +LinuxSandbox::~LinuxSandbox() { |
| + if (setuid_sandbox_) |
| + delete(setuid_sandbox_); |
|
Markus (顧孟勤)
2012/08/01 22:09:19
"delete" is an operator and not a function in C++,
jln (very slow on Chromium)
2012/08/01 22:21:53
Done.
|
| +} |
| + |
| +LinuxSandbox* LinuxSandbox::GetInstance() { |
| + LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); |
| + CHECK(instance); |
| + instance->setuid_sandbox_ = sandbox::SetuidSandboxClient::Create(); |
| + if (!instance->setuid_sandbox_) { |
| + LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; |
| + } |
| + return instance; |
| +} |
| + |
| +void LinuxSandbox::PreinitializeSandbox() { |
| + CHECK(!pre_initialized_); |
| +#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; |
| + } |
| +} |
| + |
| +// Simplify the life of the caller if they know their process type. |
| +void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) { |
| + PreinitializeSandbox(); |
| + PreinitializeSandboxFinish(process_type); |
| +} |
| + |
| +int LinuxSandbox::GetStatus() { |
| + CHECK(pre_initialized_); |
| + int sandbox_flags = 0; |
| + if (setuid_sandbox_->IsSandboxed()) { |
| + sandbox_flags |= kSandboxLinuxSUID; |
| + if (setuid_sandbox_->IsInNewPIDNamespace()) |
| + sandbox_flags |= kSandboxLinuxPIDNS; |
| + if (setuid_sandbox_->IsInNewNETNamespace()) |
| + sandbox_flags |= kSandboxLinuxNetNS; |
| + } |
| + 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; |
| +} |
| + |
| +sandbox::SetuidSandboxClient* LinuxSandbox::setuid_sandbox() { |
| + return setuid_sandbox_; |
| +} |
| + |
| +// For seccomp-legacy, we implement the policy inline, here. |
| +bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { |
| + CHECK(pre_initialized_); |
| + // Start the old seccomp mode 1 (sandbox/linux/seccomp-legacy) for renderers |
| + // only. |
| + 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; |
| +} |
| + |
| +} // namespace content |
| + |