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_TRAP_H__
6 #define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <map>
12 
13 #include "base/macros.h"
14 #include "sandbox/linux/bpf_dsl/trap_registry.h"
15 #include "sandbox/linux/system_headers/linux_signal.h"
16 #include "sandbox/sandbox_export.h"
17 
18 namespace sandbox {
19 
20 // The Trap class allows a BPF filter program to branch out to user space by
21 // raising a SIGSYS signal.
22 // N.B.: This class does not perform any synchronization operations. If
23 //   modifications are made to any of the traps, it is the caller's
24 //   responsibility to ensure that this happens in a thread-safe fashion.
25 //   Preferably, that means that no other threads should be running at that
26 //   time. For the purposes of our sandbox, this assertion should always be
27 //   true. Threads are incompatible with the seccomp sandbox anyway.
28 class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry {
29  public:
30   uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override;
31 
32   bool EnableUnsafeTraps() override;
33 
34   // Registry returns the trap registry used by Trap's SIGSYS handler,
35   // creating it if necessary.
36   static bpf_dsl::TrapRegistry* Registry();
37 
38   // SandboxDebuggingAllowedByUser returns whether the
39   // "CHROME_SANDBOX_DEBUGGING" environment variable is set.
40   static bool SandboxDebuggingAllowedByUser();
41 
42  private:
43   struct TrapKey {
TrapKeyTrapKey44     TrapKey() : fnc(NULL), aux(NULL), safe(false) {}
TrapKeyTrapKey45     TrapKey(TrapFnc f, const void* a, bool s) : fnc(f), aux(a), safe(s) {}
46     TrapFnc fnc;
47     const void* aux;
48     bool safe;
49     bool operator<(const TrapKey&) const;
50   };
51   typedef std::map<TrapKey, uint16_t> TrapIds;
52 
53   // Our constructor is private. A shared global instance is created
54   // automatically as needed.
55   Trap();
56 
57   // The destructor is unimplemented as destroying this object would
58   // break subsequent system calls that trigger a SIGSYS.
59   ~Trap() = delete;
60 
61   static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context);
62 
63   // Make sure that SigSys is not inlined in order to get slightly better crash
64   // dumps.
65   void SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx)
66       __attribute__((noinline));
67   // We have a global singleton that handles all of our SIGSYS traps. This
68   // variable must never be deallocated after it has been set up initially, as
69   // there is no way to reset in-kernel BPF filters that generate SIGSYS
70   // events.
71   static Trap* global_trap_;
72 
73   TrapIds trap_ids_;            // Maps from TrapKeys to numeric ids
74   TrapKey* trap_array_;         // Array of TrapKeys indexed by ids
75   size_t trap_array_size_;      // Currently used size of array
76   size_t trap_array_capacity_;  // Currently allocated capacity of array
77   bool has_unsafe_traps_;       // Whether unsafe traps have been enabled
78 
79   // Copying and assigning is unimplemented. It doesn't make sense for a
80   // singleton.
81   DISALLOW_COPY_AND_ASSIGN(Trap);
82 };
83 
84 }  // namespace sandbox
85 
86 #endif  // SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
87