summaryrefslogtreecommitdiff
path: root/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc')
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc88
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