diff options
Diffstat (limited to 'chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc')
-rw-r--r-- | chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc | 88 |
1 files changed, 72 insertions, 16 deletions
diff --git a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc index 639cd15e07f..3d7bc172f79 100644 --- a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc @@ -14,6 +14,7 @@ #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/files/scoped_file.h" +#include "base/logging.h" #include "base/macros.h" #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" @@ -32,6 +33,7 @@ #include "sandbox/linux/system_headers/linux_filter.h" #include "sandbox/linux/system_headers/linux_seccomp.h" #include "sandbox/linux/system_headers/linux_syscalls.h" +#include "sandbox/sandbox_buildflags.h" namespace sandbox { @@ -76,16 +78,13 @@ bool KernelHasLGBug() { return false; } -// Check if the kernel supports seccomp-filter via the seccomp system call -// and the TSYNC feature to enable seccomp on all threads. -bool KernelSupportsSeccompTsync() { +bool KernelSupportsSeccompFlags(unsigned int flags) { if (KernelHasLGBug()) { return false; } errno = 0; - const int rv = - sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr); + const int rv = sys_seccomp(SECCOMP_SET_MODE_FILTER, flags, nullptr); if (rv == -1 && errno == EFAULT) { return true; @@ -96,6 +95,20 @@ bool KernelSupportsSeccompTsync() { return false; } +// Check if the kernel supports seccomp-filter via the seccomp system call +// and the TSYNC feature to enable seccomp on all threads. +bool KernelSupportsSeccompTsync() { + return KernelSupportsSeccompFlags(SECCOMP_FILTER_FLAG_TSYNC); +} + +#if BUILDFLAG(DISABLE_SECCOMP_SSBD) +// Check if the kernel supports seccomp-filter via the seccomp system call and +// without spec flaw mitigation. +bool KernelSupportSeccompSpecAllow() { + return KernelSupportsSeccompFlags(SECCOMP_FILTER_FLAG_SPEC_ALLOW); +} +#endif + uint64_t EscapePC() { intptr_t rv = Syscall::Call(-1); if (rv == -1 && errno == ENOSYS) { @@ -170,8 +183,7 @@ bool SandboxBPF::StartSandbox(SeccompLevel seccomp_level) { } // Install the filters. - InstallFilter(supports_tsync || - seccomp_level == SeccompLevel::MULTI_THREADED); + InstallFilter(seccomp_level == SeccompLevel::MULTI_THREADED); return true; } @@ -239,23 +251,67 @@ void SandboxBPF::InstallFilter(bool must_sync_threads) { SANDBOX_DIE("Kernel refuses to enable no-new-privs"); } - // Install BPF filter program. If the thread state indicates multi-threading - // support, then the kernel hass the seccomp system call. Otherwise, fall - // back on prctl, which requires the process to be single-threaded. + // Install BPF filter program. If the thread state indicates that tsync is + // necessary or SECCOMP_FILTER_FLAG_SPEC_ALLOW is supported, then the kernel + // has the seccomp system call. Otherwise, fall back on prctl, which requires + // the process to be single-threaded. + unsigned int seccomp_filter_flags = 0; if (must_sync_threads) { - int rv = - sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, &prog); - if (rv) { - SANDBOX_DIE( - "Kernel refuses to turn on and synchronize threads for BPF filters"); - } + seccomp_filter_flags |= SECCOMP_FILTER_FLAG_TSYNC; +#if BUILDFLAG(DISABLE_SECCOMP_SSBD) + // Seccomp will disable indirect branch speculation and speculative store + // bypass simultaneously. To only opt-out SSBD, following steps are needed + // 1. Disable IBSpec with prctl + // 2. Call seccomp with SECCOMP_FILTER_FLAG_SPEC_ALLOW + // As prctl provide a per thread control of the speculation feature, only + // opt-out SSBD when process is single-threaded and tsync is not necessary. + } else if (KernelSupportSeccompSpecAllow()) { + seccomp_filter_flags |= SECCOMP_FILTER_FLAG_SPEC_ALLOW; + DisableIBSpec(); +#endif } else { if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { SANDBOX_DIE("Kernel refuses to turn on BPF filters"); } + sandbox_has_started_ = true; + return; } + int rv = sys_seccomp(SECCOMP_SET_MODE_FILTER, seccomp_filter_flags, &prog); + if (rv) { + SANDBOX_DIE("Kernel refuses to turn on BPF filters"); + } sandbox_has_started_ = true; } +void SandboxBPF::DisableIBSpec() { + // Test if the per-task control of the mitigation is available. If + // PR_SPEC_PRCTL is set, then the per-task control of the mitigation is + // available. If not set, prctl(PR_SET_SPECULATION_CTRL) for the speculation + // misfeature will fail. + const int rv = + prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0); + // Kernel control of the speculation misfeature is not supported. + if (rv < 0) { + return; + } + + if (!(rv & PR_SPEC_PRCTL)) { + DLOG(INFO) << "Indirect branch speculation can not be controled by prctl." + << rv; + return; + } + + if (rv & PR_SPEC_FORCE_DISABLE) { + DLOG(INFO) << "Indirect branch speculation is already force disabled." + << rv; + return; + } + + if (prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, + PR_SPEC_FORCE_DISABLE, 0, 0)) { + DPLOG(INFO) << "Kernel failed to force disable indirect branch speculation"; + } +} + } // namespace sandbox |