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