Home | History | Annotate | Download | only in seccomp-bpf
      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.
      4 
      5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_
      6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "base/files/scoped_file.h"
     11 #include "base/macros.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "sandbox/linux/bpf_dsl/codegen.h"
     14 #include "sandbox/sandbox_export.h"
     15 
     16 namespace sandbox {
     17 struct arch_seccomp_data;
     18 namespace bpf_dsl {
     19 class Policy;
     20 }
     21 
     22 // This class can be used to apply a syscall sandboxing policy expressed in a
     23 // bpf_dsl::Policy object to the current process.
     24 // Syscall sandboxing policies get inherited by subprocesses and, once applied,
     25 // can never be removed for the lifetime of the process.
     26 class SANDBOX_EXPORT SandboxBPF {
     27  public:
     28   enum class SeccompLevel {
     29     SINGLE_THREADED,
     30     MULTI_THREADED,
     31   };
     32 
     33   // Ownership of |policy| is transfered here to the sandbox object.
     34   // nullptr is allowed for unit tests.
     35   explicit SandboxBPF(bpf_dsl::Policy* policy);
     36   // NOTE: Setting a policy and starting the sandbox is a one-way operation.
     37   // The kernel does not provide any option for unloading a loaded sandbox. The
     38   // sandbox remains engaged even when the object is destructed.
     39   ~SandboxBPF();
     40 
     41   // Detect if the kernel supports the specified seccomp level.
     42   // See StartSandbox() for a description of these.
     43   static bool SupportsSeccompSandbox(SeccompLevel level);
     44 
     45   // This is the main public entry point. It sets up the resources needed by
     46   // the sandbox, and enters Seccomp mode.
     47   // The calling process must provide a |level| to tell the sandbox which type
     48   // of kernel support it should engage.
     49   // SINGLE_THREADED will only sandbox the calling thread. Since it would be a
     50   // security risk, the sandbox will also check that the current process is
     51   // single threaded and crash if it isn't the case.
     52   // MULTI_THREADED requires more recent kernel support and allows to sandbox
     53   // all the threads of the current process. Be mindful of potential races,
     54   // with other threads using disallowed system calls either before or after
     55   // the sandbox is engaged.
     56   //
     57   // It is possible to stack multiple sandboxes by creating separate "Sandbox"
     58   // objects and calling "StartSandbox()" on each of them. Please note, that
     59   // this requires special care, though, as newly stacked sandboxes can never
     60   // relax restrictions imposed by earlier sandboxes. Furthermore, installing
     61   // a new policy requires making system calls, that might already be
     62   // disallowed.
     63   // Finally, stacking does add more kernel overhead than having a single
     64   // combined policy. So, it should only be used if there are no alternatives.
     65   bool StartSandbox(SeccompLevel level) WARN_UNUSED_RESULT;
     66 
     67   // The sandbox needs to be able to access files in "/proc/self/". If
     68   // this directory is not accessible when "StartSandbox()" gets called, the
     69   // caller must provide an already opened file descriptor by calling
     70   // "SetProcFd()".
     71   // The sandbox becomes the new owner of this file descriptor and will
     72   // close it when "StartSandbox()" executes or when the sandbox object
     73   // disappears.
     74   void SetProcFd(base::ScopedFD proc_fd);
     75 
     76   // Checks whether a particular system call number is valid on the current
     77   // architecture.
     78   static bool IsValidSyscallNumber(int sysnum);
     79 
     80   // UnsafeTraps require some syscalls to always be allowed.
     81   // This helper function returns true for these calls.
     82   static bool IsRequiredForUnsafeTrap(int sysno);
     83 
     84   // From within an UnsafeTrap() it is often useful to be able to execute
     85   // the system call that triggered the trap. The ForwardSyscall() method
     86   // makes this easy. It is more efficient than calling glibc's syscall()
     87   // function, as it avoid the extra round-trip to the signal handler. And
     88   // it automatically does the correct thing to report kernel-style error
     89   // conditions, rather than setting errno. See the comments for TrapFnc for
     90   // details. In other words, the return value from ForwardSyscall() is
     91   // directly suitable as a return value for a trap handler.
     92   static intptr_t ForwardSyscall(const struct arch_seccomp_data& args);
     93 
     94  private:
     95   friend class SandboxBPFTestRunner;
     96 
     97   // Assembles a BPF filter program from the current policy. After calling this
     98   // function, you must not call any other sandboxing function.
     99   CodeGen::Program AssembleFilter();
    100 
    101   // Assembles and installs a filter based on the policy that has previously
    102   // been configured with SetSandboxPolicy().
    103   void InstallFilter(bool must_sync_threads);
    104 
    105   base::ScopedFD proc_fd_;
    106   bool sandbox_has_started_;
    107   scoped_ptr<bpf_dsl::Policy> policy_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(SandboxBPF);
    110 };
    111 
    112 }  // namespace sandbox
    113 
    114 #endif  // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_
    115