| Index: sandbox/linux/bpf_dsl/policy_compiler.h
|
| diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..84712ef8454dbac317bed9ff6406501008eacad8
|
| --- /dev/null
|
| +++ b/sandbox/linux/bpf_dsl/policy_compiler.h
|
| @@ -0,0 +1,174 @@
|
| +// 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 <stdint.h>
|
| +
|
| +#include <map>
|
| +#include <set>
|
| +#include <vector>
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "sandbox/linux/seccomp-bpf/codegen.h"
|
| +#include "sandbox/linux/seccomp-bpf/errorcode.h"
|
| +#include "sandbox/sandbox_export.h"
|
| +
|
| +namespace sandbox {
|
| +struct Instruction;
|
| +
|
| +namespace bpf_dsl {
|
| +class SandboxBPFDSLPolicy;
|
| +
|
| +// 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:
|
| + PolicyCompiler(const SandboxBPFDSLPolicy* policy, TrapRegistry* registry);
|
| + ~PolicyCompiler();
|
| +
|
| + // Compile registers any trap handlers needed by the policy and
|
| + // compiles the policy to a BPF program, which it returns.
|
| + scoped_ptr<CodeGen::Program> Compile();
|
| +
|
| + // Error returns an ErrorCode to indicate the system call should fail with
|
| + // the specified error number.
|
| + ErrorCode Error(int err);
|
| +
|
| + // We can use ErrorCode to request calling of a trap handler. This method
|
| + // performs the required wrapping of the callback function into an
|
| + // ErrorCode object.
|
| + // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall
|
| + // for a description of how to pass data from SetSandboxPolicy() to a Trap()
|
| + // handler.
|
| + ErrorCode Trap(TrapRegistry::TrapFnc fnc, const void* aux);
|
| +
|
| + // Calls a user-space trap handler and disables all sandboxing for system
|
| + // calls made from this trap handler.
|
| + // This feature is available only if explicitly enabled by the user having
|
| + // set the CHROME_SANDBOX_DEBUGGING environment variable.
|
| + // Returns an ET_INVALID ErrorCode, if called when not enabled.
|
| + // NOTE: This feature, by definition, disables all security features of
|
| + // the sandbox. It should never be used in production, but it can be
|
| + // very useful to diagnose code that is incompatible with the sandbox.
|
| + // If even a single system call returns "UnsafeTrap", the security of
|
| + // entire sandbox should be considered compromised.
|
| + ErrorCode UnsafeTrap(TrapRegistry::TrapFnc fnc, const void* aux);
|
| +
|
| + // UnsafeTraps require some syscalls to always be allowed.
|
| + // This helper function returns true for these calls.
|
| + static bool IsRequiredForUnsafeTrap(int sysno);
|
| +
|
| + // We can also use ErrorCode to request evaluation of a conditional
|
| + // statement based on inspection of system call parameters.
|
| + // This method wrap an ErrorCode object around the conditional statement.
|
| + // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared
|
| + // to "value"; if equal, then "passed" will be returned, otherwise "failed".
|
| + // If "is32bit" is set, 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 aborts with an error
|
| + // message).
|
| + ErrorCode CondMaskedEqual(int argno,
|
| + ErrorCode::ArgType is_32bit,
|
| + uint64_t mask,
|
| + uint64_t value,
|
| + const ErrorCode& passed,
|
| + const ErrorCode& failed);
|
| +
|
| + // Kill the program and print an error message.
|
| + ErrorCode Kill(const char* msg);
|
| +
|
| + // Returns the fatal ErrorCode that is used to indicate that somebody
|
| + // attempted to pass a 64bit value in a 32bit system call argument.
|
| + // This method is primarily needed for testing purposes.
|
| + ErrorCode Unexpected64bitArgument();
|
| +
|
| + private:
|
| + struct Range;
|
| + typedef std::vector<Range> Ranges;
|
| + typedef std::map<uint32_t, ErrorCode> ErrMap;
|
| + typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds;
|
| +
|
| + // Used by CondExpressionHalf to track which half of the argument it's
|
| + // emitting instructions for.
|
| + enum ArgHalf {
|
| + LowerHalf,
|
| + UpperHalf,
|
| + };
|
| +
|
| + // Compile the configured policy into a complete instruction sequence.
|
| + Instruction* AssemblePolicy();
|
| +
|
| + // Return an instruction sequence that checks the
|
| + // arch_seccomp_data's "arch" field is valid, and then passes
|
| + // control to |passed| if so.
|
| + Instruction* CheckArch(Instruction* passed);
|
| +
|
| + // If |has_unsafe_traps_| is true, returns an instruction sequence
|
| + // that allows all system calls from Syscall::Call(), and otherwise
|
| + // passes control to |rest|. Otherwise, simply returns |rest|.
|
| + Instruction* MaybeAddEscapeHatch(Instruction* 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.
|
| + Instruction* 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).
|
| + Instruction* CheckSyscallNumber(Instruction* 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 ErrorCodes 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.
|
| + Instruction* AssembleJumpTable(Ranges::const_iterator start,
|
| + Ranges::const_iterator stop);
|
| +
|
| + // Returns a BPF program snippet that makes the BPF filter program exit
|
| + // with the given ErrorCode "err". N.B. the ErrorCode may very well be a
|
| + // conditional expression; if so, this function will recursively call
|
| + // CondExpression() and possibly RetExpression() to build a complex set of
|
| + // instructions.
|
| + Instruction* RetExpression(const ErrorCode& err);
|
| +
|
| + // Returns a BPF program that evaluates the conditional expression in
|
| + // "cond" and returns the appropriate value from the BPF filter program.
|
| + // This function recursively calls RetExpression(); it should only ever be
|
| + // called from RetExpression().
|
| + Instruction* CondExpression(const ErrorCode& cond);
|
| +
|
| + // Returns a BPF program that evaluates half of a conditional expression;
|
| + // it should only ever be called from CondExpression().
|
| + Instruction* CondExpressionHalf(const ErrorCode& cond,
|
| + ArgHalf half,
|
| + Instruction* passed,
|
| + Instruction* failed);
|
| +
|
| + // MakeTrap is the common implementation for Trap and UnsafeTrap.
|
| + ErrorCode MakeTrap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe);
|
| +
|
| + const SandboxBPFDSLPolicy* policy_;
|
| + TrapRegistry* registry_;
|
| +
|
| + Conds conds_;
|
| + CodeGen gen_;
|
| + bool has_unsafe_traps_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(PolicyCompiler);
|
| +};
|
| +
|
| +} // namespace bpf_dsl
|
| +} // namespace sandbox
|
| +
|
| +#endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_
|
|
|