// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ #define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ #include #include #include #include "base/macros.h" #include "sandbox/linux/bpf_dsl/trap_registry.h" #include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/sandbox_export.h" namespace sandbox { // The Trap class allows a BPF filter program to branch out to user space by // raising a SIGSYS signal. // N.B.: This class does not perform any synchronization operations. If // modifications are made to any of the traps, it is the caller's // responsibility to ensure that this happens in a thread-safe fashion. // Preferably, that means that no other threads should be running at that // time. For the purposes of our sandbox, this assertion should always be // true. Threads are incompatible with the seccomp sandbox anyway. class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry { public: uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override; bool EnableUnsafeTraps() override; // Registry returns the trap registry used by Trap's SIGSYS handler, // creating it if necessary. static bpf_dsl::TrapRegistry* Registry(); // SandboxDebuggingAllowedByUser returns whether the // "CHROME_SANDBOX_DEBUGGING" environment variable is set. static bool SandboxDebuggingAllowedByUser(); private: struct TrapKey { TrapKey() : fnc(NULL), aux(NULL), safe(false) {} TrapKey(TrapFnc f, const void* a, bool s) : fnc(f), aux(a), safe(s) {} TrapFnc fnc; const void* aux; bool safe; bool operator<(const TrapKey&) const; }; typedef std::map TrapIds; // Our constructor is private. A shared global instance is created // automatically as needed. Trap(); // The destructor is unimplemented as destroying this object would // break subsequent system calls that trigger a SIGSYS. ~Trap() = delete; static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context); // Make sure that SigSys is not inlined in order to get slightly better crash // dumps. void SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) __attribute__((noinline)); // We have a global singleton that handles all of our SIGSYS traps. This // variable must never be deallocated after it has been set up initially, as // there is no way to reset in-kernel BPF filters that generate SIGSYS // events. static Trap* global_trap_; TrapIds trap_ids_; // Maps from TrapKeys to numeric ids TrapKey* trap_array_; // Array of TrapKeys indexed by ids size_t trap_array_size_; // Currently used size of array size_t trap_array_capacity_; // Currently allocated capacity of array bool has_unsafe_traps_; // Whether unsafe traps have been enabled // Copying and assigning is unimplemented. It doesn't make sense for a // singleton. DISALLOW_COPY_AND_ASSIGN(Trap); }; } // namespace sandbox #endif // SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__