Chromium Code Reviews| Index: sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| index 6ecbca99a5f3c771a7dbeb8a0dd6050932536938..82bcca315564d5a25fa1c6dd6d6f32062330ae76 100644 |
| --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| @@ -30,6 +30,7 @@ |
| #include "sandbox/linux/seccomp-bpf/syscall.h" |
| #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| #include "sandbox/linux/seccomp-bpf/verifier.h" |
| +#include "sandbox/linux/services/linux_syscalls.h" |
| namespace sandbox { |
| @@ -378,6 +379,7 @@ bool SandboxBPF::KernelSupportSeccompBPF() { |
| scoped_ptr<SandboxBPFPolicy>(new AllowAllPolicy())); |
| } |
| +// static |
| SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { |
| // It the sandbox is currently active, we clearly must have support for |
| // sandboxing. |
| @@ -433,6 +435,22 @@ SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { |
| return status_; |
| } |
| +// static |
| +SandboxBPF::SandboxStatus |
| +SandboxBPF::SupportsSeccompThreadFilterSynchronization() { |
| + int rv = syscall(__NR_seccomp); |
|
jln (very slow on Chromium)
2014/08/20 21:34:20
Do you want to add a comment saying that synchroni
Robert Sesek
2014/08/21 16:50:18
Done.
|
| + |
| + // The system call should have failed with EINVAL. |
| + if (rv != -1) |
| + return STATUS_UNKNOWN; |
|
jln (very slow on Chromium)
2014/08/20 21:34:20
Maybe add a NOTREACHED() here?
Robert Sesek
2014/08/21 16:50:17
Done.
|
| + |
| + if (errno == EINVAL) |
| + return STATUS_AVAILABLE; |
| + |
| + // errno is probably ENOSYS, indicating the system call is not available. |
| + return STATUS_UNSUPPORTED; |
|
jln (very slow on Chromium)
2014/08/20 21:34:20
DCHECK(ENOSYS == errno) maybe?
Robert Sesek
2014/08/21 16:50:18
Done.
|
| +} |
| + |
| void SandboxBPF::set_proc_fd(int proc_fd) { proc_fd_ = proc_fd; } |
| bool SandboxBPF::StartSandbox(SandboxThreadState thread_state) { |
| @@ -458,9 +476,16 @@ bool SandboxBPF::StartSandbox(SandboxThreadState thread_state) { |
| // In the future, we might want to tighten this requirement. |
| } |
| - if (thread_state == PROCESS_SINGLE_THREADED && !IsSingleThreaded(proc_fd_)) { |
| - SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded"); |
| - return false; |
| + if (SupportsSeccompThreadFilterSynchronization() == STATUS_AVAILABLE) { |
| + // The kernel supports the seccomp system call, so use that code path. |
| + thread_state = PROCESS_MULTI_THREADED; |
|
jln (very slow on Chromium)
2014/08/20 21:34:20
I would still want us to crash if the caller passe
Robert Sesek
2014/08/21 16:50:18
I actually think SandboxThreadState should just go
jln (very slow on Chromium)
2014/08/21 18:47:09
At a high level, paranoia dictates to carefully as
|
| + } else { |
| + // The kernel doesn't support the seccomp system call, so the process |
| + // must not be multi-threaded. |
| + if (!IsSingleThreaded(proc_fd_) || thread_state == PROCESS_MULTI_THREADED) { |
| + 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 |
| @@ -527,28 +552,23 @@ void SandboxBPF::InstallFilter(SandboxThreadState thread_state) { |
| conds_ = NULL; |
| policy_.reset(); |
| - // Install BPF filter program |
| - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { |
| - SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to enable no-new-privs"); |
| - } else { |
| - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { |
| - SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to turn on BPF filters"); |
| - } |
| - } |
| - |
| - // 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. |
| - |
| + // Install BPF filter program. If the thread state indicates multi-threading |
|
jln (very slow on Chromium)
2014/08/20 21:34:20
Should we still try to enable NO_NEW_PRIV via prct
Robert Sesek
2014/08/21 16:50:18
Done.
|
| + // support, then the kernel hass the seccomp system call. Otherwise, fall |
| + // back on prctl, which requires the process to be single-threaded. |
| 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."); |
| + int rv = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, |
| + SECCOMP_FILTER_FLAG_TSYNC, (const char*)&prog); |
| + if (rv) { |
| + SANDBOX_DIE(quiet_ ? NULL : |
| + "Kernel refuses to turn on and synchronize threads for BPF filters"); |
| + } |
| + } else { |
| + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { |
| + SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to enable no-new-privs"); |
| + } else { |
| + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { |
| + SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to turn on BPF filters"); |
| + } |
| } |
| } |