86 lines
3.1 KiB
C++
86 lines
3.1 KiB
C++
// 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 <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 {
|
|
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<TrapKey, uint16_t> 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__
|