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