From e8c916abb296015f9b39c8684cb17be6023147e3 Mon Sep 17 00:00:00 2001 From: "markus@chromium.org" Date: Wed, 4 Nov 2009 17:52:47 +0000 Subject: Only enable the seccomp sandbox, if the machine actually has kernel support for this feature, and if no other obstacle prevents us from enabling it. Otherwise, we print a warning message and continue running without the sandbox. This is not ideal, but given the non-trivial number of users who might not have seccomp enabled by default, this seems the prudent approach. BUG=26521 Review URL: http://codereview.chromium.org/341092 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30966 0039d316-1c4b-4281-b951-d872f2087c98 --- sandbox/linux/seccomp/sandbox.cc | 56 +++++++++++++++++++++++++++++++++++- sandbox/linux/seccomp/sandbox.h | 1 + sandbox/linux/seccomp/sandbox_impl.h | 10 +++++++ 3 files changed, 66 insertions(+), 1 deletion(-) (limited to 'sandbox/linux') diff --git a/sandbox/linux/seccomp/sandbox.cc b/sandbox/linux/seccomp/sandbox.cc index 1da17d3..9d80f63 100644 --- a/sandbox/linux/seccomp/sandbox.cc +++ b/sandbox/linux/seccomp/sandbox.cc @@ -5,13 +5,13 @@ namespace playground { // Global variables +enum Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; int Sandbox::pid_; int Sandbox::processFdPub_; int Sandbox::cloneFdPub_; Sandbox::ProtectedMap Sandbox::protectedMap_; std::vector Sandbox::secureMemPool_; - bool Sandbox::sendFd(int transport, int fd0, int fd1, const void* buf, size_t len) { int fds[2], count = 0; @@ -354,7 +354,56 @@ void Sandbox::snapshotMemoryMappings(int processFd) { } } +int Sandbox::supportsSeccompSandbox() { + if (status_ != STATUS_UNKNOWN) { + return status_ != STATUS_UNSUPPORTED; + } + int fds[2]; + SysCalls sys; + if (sys.pipe(fds)) { + status_ = STATUS_UNSUPPORTED; + return 0; + } + pid_t pid; + switch ((pid = sys.fork())) { + case -1: + status_ = STATUS_UNSUPPORTED; + return 0; + case 0: { + int devnull = sys.open("/dev/null", O_RDWR, 0); + if (devnull >= 0) { + dup2(devnull, 0); + dup2(devnull, 1); + dup2(devnull, 2); + } + startSandbox(); + write(sys, fds[1], "", 1); + _exit(0); + sys.exit_group(0); + sys._exit(0); + } + default: + NOINTR_SYS(sys.close(fds[1])); + char ch; + if (read(sys, fds[0], &ch, 1) != 1) { + status_ = STATUS_UNSUPPORTED; + } else { + status_ = STATUS_AVAILABLE; + } + int rc; + NOINTR_SYS(sys.waitpid(pid, &rc, 0)); + NOINTR_SYS(sys.close(fds[0])); + return status_ != STATUS_UNSUPPORTED; + } +} + void Sandbox::startSandbox() { + if (status_ == STATUS_UNSUPPORTED) { + die("The seccomp sandbox is not supported on this computer"); + } else if (status_ == STATUS_ENABLED) { + return; + } + SysCalls sys; // The pid is unchanged for the entire program, so we can retrieve it once @@ -425,6 +474,11 @@ void Sandbox::startSandbox() { // Creating the trusted thread enables sandboxing createTrustedThread(processFdPub_, cloneFdPub_, secureMem); + + // We can no longer check for sandboxing support at this point, but we also + // know for a fact that it is available (as we just turned it on). So update + // the status to reflect this information. + status_ = STATUS_ENABLED; } } // namespace diff --git a/sandbox/linux/seccomp/sandbox.h b/sandbox/linux/seccomp/sandbox.h index 959156b..4c5d10a 100644 --- a/sandbox/linux/seccomp/sandbox.h +++ b/sandbox/linux/seccomp/sandbox.h @@ -1,6 +1,7 @@ #ifndef SANDBOX_H__ #define SANDBOX_H__ +extern "C" int SupportsSeccompSandbox(); extern "C" void StartSeccompSandbox(); #endif // SANDBOX_H__ diff --git a/sandbox/linux/seccomp/sandbox_impl.h b/sandbox/linux/seccomp/sandbox_impl.h index 634f301..d1cc3ef 100644 --- a/sandbox/linux/seccomp/sandbox_impl.h +++ b/sandbox/linux/seccomp/sandbox_impl.h @@ -44,6 +44,13 @@ class Sandbox { public: enum { kMaxThreads = 100 }; + + // There are a lot of reasons why the Seccomp sandbox might not be available. + // This could be because the kernel does not support Seccomp mode, or it + // could be because we fail to successfully rewrite all system call entry + // points. + static int supportsSeccompSandbox() asm("SupportsSeccompSandbox"); + // This is the main public entry point. It finds all system calls that // need rewriting, sets up the resources needed by the sandbox, and // enters Seccomp mode. @@ -602,6 +609,9 @@ class Sandbox { static void createTrustedThread(int processFdPub, int cloneFdPub, SecureMem::Args* secureMem); + static enum SandboxStatus { + STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED + } status_; static int pid_; static int processFdPub_; static int cloneFdPub_; -- cgit v1.1