blob: a73d2064b475771ac57c9616f68dfdfd8b70913d [file] [log] [blame]
// 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.
#include <stddef.h>
#include <stdint.h>
#include <map>
#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 {
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();
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<TrapKey, uint16_t> TrapIds;
// Our constructor is private. A shared global instance is created
// automatically as needed.
// 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)
// 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.
} // namespace sandbox