summaryrefslogtreecommitdiff
path: root/chromium/sandbox/linux/seccomp-bpf
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/sandbox/linux/seccomp-bpf')
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/bpf_tests.h2
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc88
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h7
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/trap.cc6
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/trap.h2
5 files changed, 84 insertions, 21 deletions
diff --git a/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h b/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h
index 8b2b12afd8f..5e35e997d72 100644
--- a/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h"
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
diff --git a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 282852992b2..98475061bf2 100644
--- a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -101,6 +101,13 @@ class SANDBOX_EXPORT SandboxBPF {
// been configured with SetSandboxPolicy().
void InstallFilter(bool must_sync_threads);
+ // Disable indirect branch speculation by prctl. This will be done by
+ // seccomp if SECCOMP_FILTER_FLAG_SPEC_ALLOW is not set. Seccomp will
+ // disable indirect branch speculation and speculative store bypass
+ // simultaneously. We use prctl in supplement to control the speculation
+ // features separately.
+ void DisableIBSpec();
+
base::ScopedFD proc_fd_;
bool sandbox_has_started_;
std::unique_ptr<bpf_dsl::Policy> policy_;
diff --git a/chromium/sandbox/linux/seccomp-bpf/trap.cc b/chromium/sandbox/linux/seccomp-bpf/trap.cc
index 9884be8bb2c..f5b86a73ac7 100644
--- a/chromium/sandbox/linux/seccomp-bpf/trap.cc
+++ b/chromium/sandbox/linux/seccomp-bpf/trap.cc
@@ -60,7 +60,7 @@ bool GetIsInSigHandler(const ucontext_t* ctx) {
void SetIsInSigHandler() {
sigset_t mask;
if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) ||
- sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) {
+ sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, nullptr)) {
SANDBOX_DIE("Failed to block SIGBUS");
}
}
@@ -77,7 +77,7 @@ bool IsDefaultSignalAction(const struct sigaction& sa) {
namespace sandbox {
Trap::Trap()
- : trap_array_(NULL),
+ : trap_array_(nullptr),
trap_array_size_(0),
trap_array_capacity_(0),
has_unsafe_traps_(false) {
@@ -104,7 +104,7 @@ Trap::Trap()
// Unmask SIGSYS
sigset_t mask;
if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) ||
- sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) {
+ sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, nullptr)) {
SANDBOX_DIE("Failed to configure SIGSYS handler");
}
}
diff --git a/chromium/sandbox/linux/seccomp-bpf/trap.h b/chromium/sandbox/linux/seccomp-bpf/trap.h
index a73d2064b47..6568a9b7b40 100644
--- a/chromium/sandbox/linux/seccomp-bpf/trap.h
+++ b/chromium/sandbox/linux/seccomp-bpf/trap.h
@@ -41,7 +41,7 @@ class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry {
private:
struct TrapKey {
- TrapKey() : fnc(NULL), aux(NULL), safe(false) {}
+ TrapKey() : fnc(nullptr), aux(nullptr), safe(false) {}
TrapKey(TrapFnc f, const void* a, bool s) : fnc(f), aux(a), safe(s) {}
TrapFnc fnc;
const void* aux;