#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
SANDBOX_DIE(static_cast<char*>(aux));
}
-// This class allows compatibility with the old, deprecated SetSandboxPolicy.
-class CompatibilityPolicy : public SandboxBPFPolicy {
- public:
- CompatibilityPolicy(SandboxBPF::EvaluateSyscall syscall_evaluator, void* aux)
- : syscall_evaluator_(syscall_evaluator), aux_(aux) {
- DCHECK(syscall_evaluator_);
- }
-
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE {
- return syscall_evaluator_(sandbox_compiler, system_call_number, aux_);
- }
-
- private:
- SandboxBPF::EvaluateSyscall syscall_evaluator_;
- void* aux_;
- DISALLOW_COPY_AND_ASSIGN(CompatibilityPolicy);
-};
-
} // namespace
SandboxBPF::SandboxBPF()
}
SetSandboxPolicyDeprecated(syscall_evaluator, aux);
- StartSandbox();
+ if (!StartSandbox(PROCESS_SINGLE_THREADED)) {
+ SANDBOX_DIE(NULL);
+ }
// Run our code in the sandbox.
code_in_sandbox();
void SandboxBPF::set_proc_fd(int proc_fd) { proc_fd_ = proc_fd; }
-void SandboxBPF::StartSandbox() {
+bool SandboxBPF::StartSandbox(SandboxThreadState thread_state) {
+ CHECK(thread_state == PROCESS_SINGLE_THREADED ||
+ thread_state == PROCESS_MULTI_THREADED);
+
if (status_ == STATUS_UNSUPPORTED || status_ == STATUS_UNAVAILABLE) {
SANDBOX_DIE(
"Trying to start sandbox, even though it is known to be "
"unavailable");
+ return false;
} else if (sandbox_has_started_ || !conds_) {
SANDBOX_DIE(
"Cannot repeatedly start sandbox. Create a separate Sandbox "
"object instead.");
+ return false;
}
if (proc_fd_ < 0) {
proc_fd_ = open("/proc", O_RDONLY | O_DIRECTORY);
// For now, continue in degraded mode, if we can't access /proc.
// In the future, we might want to tighten this requirement.
}
- if (!IsSingleThreaded(proc_fd_)) {
+
+ if (thread_state == PROCESS_SINGLE_THREADED && !IsSingleThreaded(proc_fd_)) {
SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded");
+ return false;
}
// We no longer need access to any files in /proc. We want to do this
if (proc_fd_ >= 0) {
if (IGNORE_EINTR(close(proc_fd_))) {
SANDBOX_DIE("Failed to close file descriptor for /proc");
+ return false;
}
proc_fd_ = -1;
}
// Install the filters.
- InstallFilter();
+ InstallFilter(thread_state);
// We are now inside the sandbox.
status_ = STATUS_ENABLED;
+
+ return true;
}
void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) {
if (sandbox_has_started_ || !conds_) {
SANDBOX_DIE("Cannot change policy after sandbox has started");
}
- SetSandboxPolicy(new CompatibilityPolicy(syscall_evaluator, aux));
+ SetSandboxPolicy(new CompatibilityPolicy<void>(syscall_evaluator, aux));
}
// Don't take a scoped_ptr here, polymorphism make their use awkward.
policy_.reset(policy);
}
-void SandboxBPF::InstallFilter() {
+void SandboxBPF::InstallFilter(SandboxThreadState thread_state) {
// We want to be very careful in not imposing any requirements on the
// policies that are set with SetSandboxPolicy(). This means, as soon as
// the sandbox is active, we shouldn't be relying on libraries that could
}
}
- sandbox_has_started_ = true;
+ // TODO(rsesek): Always try to engage the sandbox with the
+ // PROCESS_MULTI_THREADED path first, and if that fails, assert that the
+ // process IsSingleThreaded() or SANDBOX_DIE.
+
+ if (thread_state == PROCESS_MULTI_THREADED) {
+ // TODO(rsesek): Move these to a more reasonable place once the kernel
+ // patch has landed upstream and these values are formalized.
+ #define PR_SECCOMP_EXT 41
+ #define SECCOMP_EXT_ACT 1
+ #define SECCOMP_EXT_ACT_TSYNC 1
+ if (prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0)) {
+ SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to synchronize threadgroup "
+ "BPF filters.");
+ }
+ }
- return;
+ sandbox_has_started_ = true;
}
SandboxBPF::Program* SandboxBPF::AssembleFilter(bool force_verification) {