1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
7 // Some headers on Android are missing cdefs: crbug.com/172337.
8 // (We can't use OS_ANDROID here since build_config.h is not included).
10 #include <sys/cdefs.h>
14 #include <linux/filter.h>
15 #include <sys/prctl.h>
16 #include <sys/types.h>
19 #include "base/compiler_specific.h"
20 #include "base/files/scoped_file.h"
21 #include "base/logging.h"
22 #include "base/macros.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/posix/eintr_wrapper.h"
25 #include "base/third_party/valgrind/valgrind.h"
26 #include "sandbox/linux/bpf_dsl/codegen.h"
27 #include "sandbox/linux/bpf_dsl/dump_bpf.h"
28 #include "sandbox/linux/bpf_dsl/policy.h"
29 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
30 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
31 #include "sandbox/linux/bpf_dsl/syscall_set.h"
32 #include "sandbox/linux/seccomp-bpf/die.h"
33 #include "sandbox/linux/seccomp-bpf/errorcode.h"
34 #include "sandbox/linux/seccomp-bpf/syscall.h"
35 #include "sandbox/linux/seccomp-bpf/trap.h"
36 #include "sandbox/linux/seccomp-bpf/verifier.h"
37 #include "sandbox/linux/services/proc_util.h"
38 #include "sandbox/linux/services/syscall_wrappers.h"
39 #include "sandbox/linux/services/thread_helpers.h"
40 #include "sandbox/linux/system_headers/linux_seccomp.h"
41 #include "sandbox/linux/system_headers/linux_syscalls.h"
47 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND
; }
49 bool IsSingleThreaded(int proc_fd
) {
50 return ThreadHelpers::IsSingleThreaded(proc_fd
);
53 // Check if the kernel supports seccomp-filter (a.k.a. seccomp mode 2) via
55 bool KernelSupportsSeccompBPF() {
57 const int rv
= prctl(PR_SET_SECCOMP
, SECCOMP_MODE_FILTER
, nullptr);
59 if (rv
== -1 && EFAULT
== errno
) {
65 // Check if the kernel supports seccomp-filter via the seccomp system call
66 // and the TSYNC feature to enable seccomp on all threads.
67 bool KernelSupportsSeccompTsync() {
70 sys_seccomp(SECCOMP_SET_MODE_FILTER
, SECCOMP_FILTER_FLAG_TSYNC
, nullptr);
72 if (rv
== -1 && errno
== EFAULT
) {
75 // TODO(jln): turn these into DCHECK after 417888 is considered fixed.
77 CHECK(ENOSYS
== errno
|| EINVAL
== errno
);
84 SandboxBPF::SandboxBPF(bpf_dsl::Policy
* policy
)
85 : proc_fd_(), sandbox_has_started_(false), policy_(policy
) {
88 SandboxBPF::~SandboxBPF() {
92 bool SandboxBPF::SupportsSeccompSandbox(SeccompLevel level
) {
93 // Never pretend to support seccomp with Valgrind, as it
94 // throws the tool off.
95 if (IsRunningOnValgrind()) {
100 case SeccompLevel::SINGLE_THREADED
:
101 return KernelSupportsSeccompBPF();
102 case SeccompLevel::MULTI_THREADED
:
103 return KernelSupportsSeccompTsync();
109 bool SandboxBPF::StartSandbox(SeccompLevel seccomp_level
) {
111 CHECK(seccomp_level
== SeccompLevel::SINGLE_THREADED
||
112 seccomp_level
== SeccompLevel::MULTI_THREADED
);
114 if (sandbox_has_started_
) {
116 "Cannot repeatedly start sandbox. Create a separate Sandbox "
121 if (!proc_fd_
.is_valid()) {
122 SetProcFd(ProcUtil::OpenProc());
125 const bool supports_tsync
= KernelSupportsSeccompTsync();
127 if (seccomp_level
== SeccompLevel::SINGLE_THREADED
) {
128 // Wait for /proc/self/task/ to update if needed and assert the
129 // process is single threaded.
130 ThreadHelpers::AssertSingleThreaded(proc_fd_
.get());
131 } else if (seccomp_level
== SeccompLevel::MULTI_THREADED
) {
132 if (IsSingleThreaded(proc_fd_
.get())) {
133 SANDBOX_DIE("Cannot start sandbox; "
134 "process may be single-threaded when reported as not");
137 if (!supports_tsync
) {
138 SANDBOX_DIE("Cannot start sandbox; kernel does not support synchronizing "
139 "filters for a threadgroup");
144 // We no longer need access to any files in /proc. We want to do this
145 // before installing the filters, just in case that our policy denies
147 if (proc_fd_
.is_valid()) {
151 // Install the filters.
152 InstallFilter(supports_tsync
||
153 seccomp_level
== SeccompLevel::MULTI_THREADED
);
158 void SandboxBPF::SetProcFd(base::ScopedFD proc_fd
) {
159 proc_fd_
.swap(proc_fd
);
163 bool SandboxBPF::IsValidSyscallNumber(int sysnum
) {
164 return SyscallSet::IsValid(sysnum
);
168 bool SandboxBPF::IsRequiredForUnsafeTrap(int sysno
) {
169 return bpf_dsl::PolicyCompiler::IsRequiredForUnsafeTrap(sysno
);
173 intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data
& args
) {
174 return Syscall::Call(
175 args
.nr
, static_cast<intptr_t>(args
.args
[0]),
176 static_cast<intptr_t>(args
.args
[1]), static_cast<intptr_t>(args
.args
[2]),
177 static_cast<intptr_t>(args
.args
[3]), static_cast<intptr_t>(args
.args
[4]),
178 static_cast<intptr_t>(args
.args
[5]));
181 scoped_ptr
<CodeGen::Program
> SandboxBPF::AssembleFilter(
182 bool force_verification
) {
184 force_verification
= true;
187 bpf_dsl::PolicyCompiler
compiler(policy_
.get(), Trap::Registry());
188 scoped_ptr
<CodeGen::Program
> program
= compiler
.Compile();
190 // Make sure compilation resulted in a BPF program that executes
191 // correctly. Otherwise, there is an internal error in our BPF compiler.
192 // There is really nothing the caller can do until the bug is fixed.
193 if (force_verification
) {
194 // Verification is expensive. We only perform this step, if we are
195 // compiled in debug mode, or if the caller explicitly requested
198 const char* err
= NULL
;
199 if (!Verifier::VerifyBPF(&compiler
, *program
, *policy_
, &err
)) {
200 bpf_dsl::DumpBPF::PrintProgram(*program
);
205 return program
.Pass();
208 void SandboxBPF::InstallFilter(bool must_sync_threads
) {
209 // We want to be very careful in not imposing any requirements on the
210 // policies that are set with SetSandboxPolicy(). This means, as soon as
211 // the sandbox is active, we shouldn't be relying on libraries that could
212 // be making system calls. This, for example, means we should avoid
213 // using the heap and we should avoid using STL functions.
214 // Temporarily copy the contents of the "program" vector into a
215 // stack-allocated array; and then explicitly destroy that object.
216 // This makes sure we don't ex- or implicitly call new/delete after we
217 // installed the BPF filter program in the kernel. Depending on the
218 // system memory allocator that is in effect, these operators can result
219 // in system calls to things like munmap() or brk().
220 CodeGen::Program
* program
= AssembleFilter(false).release();
222 struct sock_filter bpf
[program
->size()];
223 const struct sock_fprog prog
= {static_cast<unsigned short>(program
->size()),
225 memcpy(bpf
, &(*program
)[0], sizeof(bpf
));
228 // Make an attempt to release memory that is no longer needed here, rather
229 // than in the destructor. Try to avoid as much as possible to presume of
230 // what will be possible to do in the new (sandboxed) execution environment.
233 if (prctl(PR_SET_NO_NEW_PRIVS
, 1, 0, 0, 0)) {
234 SANDBOX_DIE("Kernel refuses to enable no-new-privs");
237 // Install BPF filter program. If the thread state indicates multi-threading
238 // support, then the kernel hass the seccomp system call. Otherwise, fall
239 // back on prctl, which requires the process to be single-threaded.
240 if (must_sync_threads
) {
242 sys_seccomp(SECCOMP_SET_MODE_FILTER
, SECCOMP_FILTER_FLAG_TSYNC
, &prog
);
245 "Kernel refuses to turn on and synchronize threads for BPF filters");
248 if (prctl(PR_SET_SECCOMP
, SECCOMP_MODE_FILTER
, &prog
)) {
249 SANDBOX_DIE("Kernel refuses to turn on BPF filters");
253 sandbox_has_started_
= true;
256 } // namespace sandbox