15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/compiler_specific.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/errorcode.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "sandbox/linux/seccomp-bpf/trap.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sandbox/sandbox_export.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct sock_filter; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace sandbox { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CodeGen; 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class SandboxBPFPolicy; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SandboxUnittestHelper; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Instruction; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass SANDBOX_EXPORT SandboxBPF { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum SandboxStatus { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATUS_UNAVAILABLE, // Currently unavailable but might work again later 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATUS_AVAILABLE, // Sandboxing is available but not currently active 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATUS_ENABLED // The sandbox is now active 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Depending on the level of kernel support, seccomp-bpf may require the 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // process to be single-threaded in order to enable it. When calling 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // StartSandbox(), the program should indicate whether or not the sandbox 41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // should try and engage with multi-thread support. 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch enum SandboxThreadState { 43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PROCESS_INVALID, 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PROCESS_SINGLE_THREADED, // The program is currently single-threaded. 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Note: PROCESS_MULTI_THREADED requires experimental kernel support that 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // has not been contributed to upstream Linux. 47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PROCESS_MULTI_THREADED, // The program may be multi-threaded. 48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A vector of BPF instructions that need to be installed as a filter 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // program in the kernel. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::vector<struct sock_filter> Program; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Constructors and destructors. 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // NOTE: Setting a policy and starting the sandbox is a one-way operation. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The kernel does not provide any option for unloading a loaded 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sandbox. Strictly speaking, that means we should disallow calling 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the destructor, if StartSandbox() has ever been called. In practice, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this makes it needlessly complicated to operate on "Sandbox" 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // objects. So, we instead opted to allow object destruction. But it 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // should be noted that during its lifetime, the object probably made 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // irreversible state changes to the runtime environment. These changes 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay in effect even after the destructor has been run. 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SandboxBPF(); 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ~SandboxBPF(); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks whether a particular system call number is valid on the current 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // architecture. E.g. on ARM there's a non-contiguous range of private 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system calls. 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool IsValidSyscallNumber(int sysnum); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are a lot of reasons why the Seccomp sandbox might not be available. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This could be because the kernel does not support Seccomp mode, or it 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could be because another sandbox is already active. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "proc_fd" should be a file descriptor for "/proc", or -1 if not 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // provided by the caller. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static SandboxStatus SupportsSeccompSandbox(int proc_fd); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Determines if the kernel has support for the seccomp() system call to 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // synchronize BPF filters across a thread group. 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static SandboxStatus SupportsSeccompThreadFilterSynchronization(); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The sandbox needs to be able to access files in "/proc/self". If this 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // directory is not accessible when "startSandbox()" gets called, the caller 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // can provide an already opened file descriptor by calling "set_proc_fd()". 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The sandbox becomes the new owner of this file descriptor and will 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // eventually close it when "StartSandbox()" executes. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_proc_fd(int proc_fd); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Set the BPF policy as |policy|. Ownership of |policy| is transfered here 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // to the sandbox object. 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void SetSandboxPolicy(SandboxBPFPolicy* policy); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can use ErrorCode to request calling of a trap handler. This method 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performs the required wrapping of the callback function into an 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ErrorCode object. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for a description of how to pass data from SetSandboxPolicy() to a Trap() 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handler. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ErrorCode Trap(Trap::TrapFnc fnc, const void* aux); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Calls a user-space trap handler and disables all sandboxing for system 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // calls made from this trap handler. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This feature is available only if explicitly enabled by the user having 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set the CHROME_SANDBOX_DEBUGGING environment variable. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns an ET_INVALID ErrorCode, if called when not enabled. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // NOTE: This feature, by definition, disables all security features of 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the sandbox. It should never be used in production, but it can be 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // very useful to diagnose code that is incompatible with the sandbox. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If even a single system call returns "UnsafeTrap", the security of 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // entire sandbox should be considered compromised. 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void* aux); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // UnsafeTraps require some syscalls to always be allowed. 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This helper function returns true for these calls. 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static bool IsRequiredForUnsafeTrap(int sysno); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // From within an UnsafeTrap() it is often useful to be able to execute 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the system call that triggered the trap. The ForwardSyscall() method 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // makes this easy. It is more efficient than calling glibc's syscall() 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // function, as it avoid the extra round-trip to the signal handler. And 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it automatically does the correct thing to report kernel-style error 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // conditions, rather than setting errno. See the comments for TrapFnc for 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // details. In other words, the return value from ForwardSyscall() is 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // directly suitable as a return value for a trap handler. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We can also use ErrorCode to request evaluation of a conditional 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // statement based on inspection of system call parameters. 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This method wrap an ErrorCode object around the conditional statement. 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to "value"; if equal, then "passed" will be returned, otherwise "failed". 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is outside this range, the sandbox treats the system call just 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the same as any other ABI violation (i.e. it aborts with an error 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // message). 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ErrorCode CondMaskedEqual(int argno, 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ErrorCode::ArgType is_32bit, 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint64_t mask, 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint64_t value, 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ErrorCode& passed, 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ErrorCode& failed); 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Legacy variant of CondMaskedEqual that supports a few comparison 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // operations, which get converted into masked-equality comparisons. 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ErrorCode Cond(int argno, 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ErrorCode::ArgType is_32bit, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode::Operation op, 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint64_t value, 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const ErrorCode& passed, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ErrorCode& failed); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Kill the program and print an error message. 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ErrorCode Kill(const char* msg); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the main public entry point. It finds all system calls that 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need rewriting, sets up the resources needed by the sandbox, and 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enters Seccomp mode. 159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // The calling process must specify its current SandboxThreadState, as a way 160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // to tell the sandbox which type of kernel support it should engage. 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is possible to stack multiple sandboxes by creating separate "Sandbox" 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // objects and calling "StartSandbox()" on each of them. Please note, that 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this requires special care, though, as newly stacked sandboxes can never 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // relax restrictions imposed by earlier sandboxes. Furthermore, installing 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a new policy requires making system calls, that might already be 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // disallowed. 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Finally, stacking does add more kernel overhead than having a single 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // combined policy. So, it should only be used if there are no alternatives. 169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool StartSandbox(SandboxThreadState thread_state) WARN_UNUSED_RESULT; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assembles a BPF filter program from the current policy. After calling this 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // function, you must not call any other sandboxing function. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Typically, AssembleFilter() is only used by unit tests and by sandbox 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // internals. It should not be used by production code. 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For performance reasons, we normally only run the assembled BPF program 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // through the verifier, iff the program was built in debug mode. 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // But by setting "force_verification", the caller can request that the 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // verifier is run unconditionally. This is useful for unittests. 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Program* AssembleFilter(bool force_verification); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the fatal ErrorCode that is used to indicate that somebody 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // attempted to pass a 64bit value in a 32bit system call argument. 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This method is primarily needed for testing purposes. 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ErrorCode Unexpected64bitArgument(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class CodeGen; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class SandboxUnittestHelper; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend class ErrorCode; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Range { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Range(uint32_t f, uint32_t t, const ErrorCode& e) 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : from(f), to(t), err(e) {} 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t from, to; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCode err; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<Range> Ranges; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<uint32_t, ErrorCode> ErrMap; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Used by CondExpressionHalf to track which half of the argument it's 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // emitting instructions for. 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci enum ArgHalf { 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LowerHalf, 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpperHalf, 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a file descriptor pointing to "/proc", if currently available. 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int proc_fd() { return proc_fd_; } 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates a subprocess and runs "code_in_sandbox" inside of the specified 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // policy. The caller has to make sure that "this" has not yet been 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // initialized with any other policies. 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool RunFunctionInPolicy(void (*code_in_sandbox)(), 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SandboxBPFPolicy> policy); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Performs a couple of sanity checks to verify that the kernel supports the 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // features that we need for successful sandboxing. 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The caller has to make sure that "this" has not yet been initialized with 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any other policies. 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool KernelSupportSeccompBPF(); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that the current policy passes some basic sanity checks. 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void PolicySanityChecks(SandboxBPFPolicy* policy); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assembles and installs a filter based on the policy that has previously 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // been configured with SetSandboxPolicy(). 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void InstallFilter(bool must_sync_threads); 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Compile the configured policy into a complete instruction sequence. 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (See MaybeAddEscapeHatch for |has_unsafe_traps|.) 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* CompilePolicy(CodeGen* gen, bool* has_unsafe_traps); 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Return an instruction sequence that checks the 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // arch_seccomp_data's "arch" field is valid, and then passes 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // control to |passed| if so. 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* CheckArch(CodeGen* gen, Instruction* passed); 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the |rest| instruction sequence contains any unsafe traps, 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // then sets |*has_unsafe_traps| to true and returns an instruction 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // sequence that allows all system calls from Syscall::Call(), and 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // otherwise passes control to |rest|. 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If |rest| contains no unsafe traps, then |rest| is returned 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // directly and |*has_unsafe_traps| is set to false. 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* MaybeAddEscapeHatch(CodeGen* gen, 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool* has_unsafe_traps, 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* rest); 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Return an instruction sequence that loads and checks the system 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // call number, performs a binary search, and then dispatches to an 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // appropriate instruction sequence compiled from the current 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // policy. 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* DispatchSyscall(CodeGen* gen); 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Return an instruction sequence that checks the system call number 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (expected to be loaded in register A) and if valid, passes 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // control to |passed| (with register A still valid). 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* CheckSyscallNumber(CodeGen* gen, Instruction* passed); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify the correctness of a compiled program by comparing it against the 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // current policy. This function should only ever be called by unit tests and 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // by the sandbox internals. It should not be used by production code. 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VerifyProgram(const Program& program, bool has_unsafe_traps); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Finds all the ranges of system calls that need to be handled. Ranges are 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sorted in ascending order of system call numbers. There are no gaps in the 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ranges. System calls with identical ErrorCodes are coalesced into a single 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // range. 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void FindRanges(Ranges* ranges); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns a BPF program snippet that implements a jump table for the 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // given range of system call numbers. This function runs recursively. 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Instruction* AssembleJumpTable(CodeGen* gen, 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Ranges::const_iterator start, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Ranges::const_iterator stop); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns a BPF program snippet that makes the BPF filter program exit 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // with the given ErrorCode "err". N.B. the ErrorCode may very well be a 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // conditional expression; if so, this function will recursively call 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CondExpression() and possibly RetExpression() to build a complex set of 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // instructions. 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Instruction* RetExpression(CodeGen* gen, const ErrorCode& err); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns a BPF program that evaluates the conditional expression in 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // "cond" and returns the appropriate value from the BPF filter program. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This function recursively calls RetExpression(); it should only ever be 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // called from RetExpression(). 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Instruction* CondExpression(CodeGen* gen, const ErrorCode& cond); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns a BPF program that evaluates half of a conditional expression; 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it should only ever be called from CondExpression(). 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* CondExpressionHalf(CodeGen* gen, 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ErrorCode& cond, 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ArgHalf half, 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* passed, 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Instruction* failed); 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SandboxStatus status_; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool quiet_; 302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int proc_fd_; 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<const SandboxBPFPolicy> policy_; 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Conds* conds_; 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool sandbox_has_started_; 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SandboxBPF); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sandbox 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 313