1f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// found in the LICENSE file.
4f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
5f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
6f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
7f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <errno.h>
824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include <stdint.h>
9f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <sys/prctl.h>
10f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <sys/types.h>
11f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <unistd.h>
12f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
13f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/compiler_specific.h"
14f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/files/scoped_file.h"
15f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/logging.h"
16f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/macros.h"
17f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/memory/scoped_ptr.h"
18f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/posix/eintr_wrapper.h"
1924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
20f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/bpf_dsl/codegen.h"
21f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/bpf_dsl/policy.h"
22f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/bpf_dsl/policy_compiler.h"
23f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
24f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/bpf_dsl/syscall_set.h"
25f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/seccomp-bpf/die.h"
26f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/seccomp-bpf/syscall.h"
27f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/seccomp-bpf/trap.h"
28f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/services/proc_util.h"
29f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/services/syscall_wrappers.h"
30f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/services/thread_helpers.h"
31f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/system_headers/linux_filter.h"
32f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/system_headers/linux_seccomp.h"
33f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "sandbox/linux/system_headers/linux_syscalls.h"
34f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "third_party/valgrind/valgrind.h"
35f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
36f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace sandbox {
37f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
38f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace {
39f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
40f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
41f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
42f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool IsSingleThreaded(int proc_fd) {
43f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return ThreadHelpers::IsSingleThreaded(proc_fd);
44f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
45f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
46f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Check if the kernel supports seccomp-filter (a.k.a. seccomp mode 2) via
47f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// prctl().
48f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool KernelSupportsSeccompBPF() {
49f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  errno = 0;
50f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const int rv = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr);
51f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
52f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (rv == -1 && EFAULT == errno) {
53f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return true;
54f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
55f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return false;
56f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
57f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
58f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// LG introduced a buggy syscall, sys_set_media_ext, with the same number as
59f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// seccomp. Return true if the current kernel has this buggy syscall.
60f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
61f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// We want this to work with upcoming versions of seccomp, so we pass bogus
62f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// flags that are unlikely to ever be used by the kernel. A normal kernel would
63f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// return -EINVAL, but a buggy LG kernel would return 1.
64f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool KernelHasLGBug() {
65f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#if defined(OS_ANDROID)
66f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // sys_set_media will see this as NULL, which should be a safe (non-crashing)
67f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // way to invoke it. A genuine seccomp syscall will see it as
68f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // SECCOMP_SET_MODE_STRICT.
69f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const unsigned int operation = 0;
70f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Chosen by fair dice roll. Guaranteed to be random.
71f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const unsigned int flags = 0xf7a46a5c;
72f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const int rv = sys_seccomp(operation, flags, nullptr);
73f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // A genuine kernel would return -EINVAL (which would set rv to -1 and errno
74f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // to EINVAL), or at the very least return some kind of error (which would
75f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // set rv to -1). Any other behavior indicates that whatever code received
76f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // our syscall was not the real seccomp.
77f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (rv != -1) {
78f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return true;
79f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
80f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#endif  // defined(OS_ANDROID)
81f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
82f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return false;
83f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
84f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
85f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Check if the kernel supports seccomp-filter via the seccomp system call
86f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// and the TSYNC feature to enable seccomp on all threads.
87f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool KernelSupportsSeccompTsync() {
88f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (KernelHasLGBug()) {
89f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return false;
90f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
91f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
92f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  errno = 0;
93f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const int rv =
94f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr);
95f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
96f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (rv == -1 && errno == EFAULT) {
97f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return true;
98f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  } else {
99f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // TODO(jln): turn these into DCHECK after 417888 is considered fixed.
100f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    CHECK_EQ(-1, rv);
101f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    CHECK(ENOSYS == errno || EINVAL == errno);
102f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return false;
103f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
104f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
105f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
106f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkouint64_t EscapePC() {
107f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  intptr_t rv = Syscall::Call(-1);
108f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (rv == -1 && errno == ENOSYS) {
109f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return 0;
110f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
111f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return static_cast<uint64_t>(static_cast<uintptr_t>(rv));
112f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
113f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
11424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkointptr_t SandboxPanicTrap(const struct arch_seccomp_data&, void* aux) {
11524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  SANDBOX_DIE(static_cast<const char*>(aux));
11624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko}
11724854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko
11824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkobpf_dsl::ResultExpr SandboxPanic(const char* error) {
11924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  return bpf_dsl::Trap(SandboxPanicTrap, error);
12024854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko}
12124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko
122f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace
123f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
124f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSandboxBPF::SandboxBPF(bpf_dsl::Policy* policy)
125f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    : proc_fd_(), sandbox_has_started_(false), policy_(policy) {
126f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
127f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
128f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSandboxBPF::~SandboxBPF() {
129f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
130f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
131f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static
132f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool SandboxBPF::SupportsSeccompSandbox(SeccompLevel level) {
133f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Never pretend to support seccomp with Valgrind, as it
134f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // throws the tool off.
135f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (IsRunningOnValgrind()) {
136f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return false;
137f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
138f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
139f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  switch (level) {
140f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case SeccompLevel::SINGLE_THREADED:
141f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return KernelSupportsSeccompBPF();
142f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case SeccompLevel::MULTI_THREADED:
143f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return KernelSupportsSeccompTsync();
144f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
145f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  NOTREACHED();
146f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return false;
147f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
148f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
149f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool SandboxBPF::StartSandbox(SeccompLevel seccomp_level) {
150f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  DCHECK(policy_);
151f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  CHECK(seccomp_level == SeccompLevel::SINGLE_THREADED ||
152f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        seccomp_level == SeccompLevel::MULTI_THREADED);
153f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
154f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (sandbox_has_started_) {
155f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    SANDBOX_DIE(
156f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        "Cannot repeatedly start sandbox. Create a separate Sandbox "
157f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        "object instead.");
158f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return false;
159f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
160f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
161f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (!proc_fd_.is_valid()) {
162f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    SetProcFd(ProcUtil::OpenProc());
163f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
164f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
165f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  const bool supports_tsync = KernelSupportsSeccompTsync();
166f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
167f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (seccomp_level == SeccompLevel::SINGLE_THREADED) {
168f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // Wait for /proc/self/task/ to update if needed and assert the
169f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // process is single threaded.
170f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    ThreadHelpers::AssertSingleThreaded(proc_fd_.get());
171f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  } else if (seccomp_level == SeccompLevel::MULTI_THREADED) {
172f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    if (IsSingleThreaded(proc_fd_.get())) {
173f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      SANDBOX_DIE("Cannot start sandbox; "
174f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                  "process may be single-threaded when reported as not");
175f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return false;
176f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
177f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    if (!supports_tsync) {
178f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      SANDBOX_DIE("Cannot start sandbox; kernel does not support synchronizing "
179f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                  "filters for a threadgroup");
180f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return false;
181f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
182f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
183f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
184f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // We no longer need access to any files in /proc. We want to do this
185f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // before installing the filters, just in case that our policy denies
186f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // close().
187f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (proc_fd_.is_valid()) {
188f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    proc_fd_.reset();
189f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
190f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
191f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Install the filters.
192f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  InstallFilter(supports_tsync ||
193f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                seccomp_level == SeccompLevel::MULTI_THREADED);
194f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
195f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return true;
196f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
197f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
198f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid SandboxBPF::SetProcFd(base::ScopedFD proc_fd) {
199f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  proc_fd_.swap(proc_fd);
200f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
201f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
202f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static
203f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool SandboxBPF::IsValidSyscallNumber(int sysnum) {
204f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return SyscallSet::IsValid(sysnum);
205f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
206f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
207f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static
208f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool SandboxBPF::IsRequiredForUnsafeTrap(int sysno) {
209f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return bpf_dsl::PolicyCompiler::IsRequiredForUnsafeTrap(sysno);
210f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
211f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
212f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static
213f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkointptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) {
214f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return Syscall::Call(
215f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      args.nr, static_cast<intptr_t>(args.args[0]),
216f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      static_cast<intptr_t>(args.args[1]), static_cast<intptr_t>(args.args[2]),
217f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      static_cast<intptr_t>(args.args[3]), static_cast<intptr_t>(args.args[4]),
218f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      static_cast<intptr_t>(args.args[5]));
219f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
220f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
22124854748fba09df2a29f0d08d558c3acea70e7a1Alex VakulenkoCodeGen::Program SandboxBPF::AssembleFilter() {
222f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  DCHECK(policy_);
223f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
224f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bpf_dsl::PolicyCompiler compiler(policy_.get(), Trap::Registry());
225f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (Trap::SandboxDebuggingAllowedByUser()) {
226f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    compiler.DangerousSetEscapePC(EscapePC());
227f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
22824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  compiler.SetPanicFunc(SandboxPanic);
22924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  return compiler.Compile();
230f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
231f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
232f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid SandboxBPF::InstallFilter(bool must_sync_threads) {
233f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // We want to be very careful in not imposing any requirements on the
234f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // policies that are set with SetSandboxPolicy(). This means, as soon as
235f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // the sandbox is active, we shouldn't be relying on libraries that could
236f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // be making system calls. This, for example, means we should avoid
237f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // using the heap and we should avoid using STL functions.
238f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Temporarily copy the contents of the "program" vector into a
239f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // stack-allocated array; and then explicitly destroy that object.
240f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // This makes sure we don't ex- or implicitly call new/delete after we
241f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // installed the BPF filter program in the kernel. Depending on the
242f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // system memory allocator that is in effect, these operators can result
243f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // in system calls to things like munmap() or brk().
24424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  CodeGen::Program program = AssembleFilter();
245f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
24624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  struct sock_filter bpf[program.size()];
24724854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  const struct sock_fprog prog = {static_cast<unsigned short>(program.size()),
248f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                                  bpf};
24924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  memcpy(bpf, &program[0], sizeof(bpf));
25024854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  CodeGen::Program().swap(program);  // vector swap trick
251f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
252f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Make an attempt to release memory that is no longer needed here, rather
253f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // than in the destructor. Try to avoid as much as possible to presume of
254f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // what will be possible to do in the new (sandboxed) execution environment.
255f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  policy_.reset();
256f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
257f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
258f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    SANDBOX_DIE("Kernel refuses to enable no-new-privs");
259f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
260f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
261f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Install BPF filter program. If the thread state indicates multi-threading
262f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // support, then the kernel hass the seccomp system call. Otherwise, fall
263f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // back on prctl, which requires the process to be single-threaded.
264f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (must_sync_threads) {
265f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    int rv =
266f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, &prog);
267f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    if (rv) {
268f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      SANDBOX_DIE(
269f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          "Kernel refuses to turn on and synchronize threads for BPF filters");
270f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
271f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  } else {
272f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
273f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      SANDBOX_DIE("Kernel refuses to turn on BPF filters");
274f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
275f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
276f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
277f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  sandbox_has_started_ = true;
278f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
279f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
280f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace sandbox
281