diff options
Diffstat (limited to 'security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h')
-rw-r--r-- | security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h new file mode 100644 index 000000000..48b1d780d --- /dev/null +++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h @@ -0,0 +1,153 @@ +// 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_BPF_DSL_POLICY_COMPILER_H_ +#define SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "base/macros.h" +#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" +#include "sandbox/linux/bpf_dsl/codegen.h" +#include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/sandbox_export.h" + +namespace sandbox { +namespace bpf_dsl { +class Policy; + +// PolicyCompiler implements the bpf_dsl compiler, allowing users to +// transform bpf_dsl policies into BPF programs to be executed by the +// Linux kernel. +class SANDBOX_EXPORT PolicyCompiler { + public: + using PanicFunc = bpf_dsl::ResultExpr (*)(const char* error); + + PolicyCompiler(const Policy* policy, TrapRegistry* registry); + ~PolicyCompiler(); + + // Compile registers any trap handlers needed by the policy and + // compiles the policy to a BPF program, which it returns. + CodeGen::Program Compile(); + + // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any + // system calls, regardless of policy. + void DangerousSetEscapePC(uint64_t escapepc); + + // SetPanicFunc sets the callback function used for handling faulty + // system call conditions. The default behavior is to immediately kill + // the process. + // TODO(mdempsky): Move this into Policy? + void SetPanicFunc(PanicFunc panic_func); + + // UnsafeTraps require some syscalls to always be allowed. + // This helper function returns true for these calls. + static bool IsRequiredForUnsafeTrap(int sysno); + + // Functions below are meant for use within bpf_dsl itself. + + // Return returns a CodeGen::Node that returns the specified seccomp + // return value. + CodeGen::Node Return(uint32_t ret); + + // Trap returns a CodeGen::Node to indicate the system call should + // instead invoke a trap handler. + CodeGen::Node Trap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe); + + // MaskedEqual returns a CodeGen::Node that represents a conditional branch. + // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared + // to "value"; if equal, then "passed" will be executed, otherwise "failed". + // If "width" is 4, the argument must in the range of 0x0..(1u << 32 - 1) + // If it is outside this range, the sandbox treats the system call just + // the same as any other ABI violation (i.e., it panics). + CodeGen::Node MaskedEqual(int argno, + size_t width, + uint64_t mask, + uint64_t value, + CodeGen::Node passed, + CodeGen::Node failed); + + private: + struct Range; + typedef std::vector<Range> Ranges; + + // Used by MaskedEqualHalf to track which half of the argument it's + // emitting instructions for. + enum class ArgHalf { + LOWER, + UPPER, + }; + + // Compile the configured policy into a complete instruction sequence. + CodeGen::Node AssemblePolicy(); + + // Return an instruction sequence that checks the + // arch_seccomp_data's "arch" field is valid, and then passes + // control to |passed| if so. + CodeGen::Node CheckArch(CodeGen::Node passed); + + // If |has_unsafe_traps_| is true, returns an instruction sequence + // that allows all system calls from |escapepc_|, and otherwise + // passes control to |rest|. Otherwise, simply returns |rest|. + CodeGen::Node MaybeAddEscapeHatch(CodeGen::Node rest); + + // Return an instruction sequence that loads and checks the system + // call number, performs a binary search, and then dispatches to an + // appropriate instruction sequence compiled from the current + // policy. + CodeGen::Node DispatchSyscall(); + + // Return an instruction sequence that checks the system call number + // (expected to be loaded in register A) and if valid, passes + // control to |passed| (with register A still valid). + CodeGen::Node CheckSyscallNumber(CodeGen::Node passed); + + // Finds all the ranges of system calls that need to be handled. Ranges are + // sorted in ascending order of system call numbers. There are no gaps in the + // ranges. System calls with identical CodeGen::Nodes are coalesced into a + // single + // range. + void FindRanges(Ranges* ranges); + + // Returns a BPF program snippet that implements a jump table for the + // given range of system call numbers. This function runs recursively. + CodeGen::Node AssembleJumpTable(Ranges::const_iterator start, + Ranges::const_iterator stop); + + // CompileResult compiles an individual result expression into a + // CodeGen node. + CodeGen::Node CompileResult(const ResultExpr& res); + + // Returns a BPF program that evaluates half of a conditional expression; + // it should only ever be called from CondExpression(). + CodeGen::Node MaskedEqualHalf(int argno, + size_t width, + uint64_t full_mask, + uint64_t full_value, + ArgHalf half, + CodeGen::Node passed, + CodeGen::Node failed); + + // Returns the fatal CodeGen::Node that is used to indicate that somebody + // attempted to pass a 64bit value in a 32bit system call argument. + CodeGen::Node Unexpected64bitArgument(); + + const Policy* policy_; + TrapRegistry* registry_; + uint64_t escapepc_; + PanicFunc panic_func_; + + CodeGen gen_; + bool has_unsafe_traps_; + + DISALLOW_COPY_AND_ASSIGN(PolicyCompiler); +}; + +} // namespace bpf_dsl +} // namespace sandbox + +#endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ |