| // 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_ERRORCODE_H__ |
| #define SANDBOX_LINUX_SECCOMP_BPF_ERRORCODE_H__ |
| |
| namespace playground2 { |
| |
| struct arch_seccomp_data; |
| |
| // This class holds all the possible values that can returned by a sandbox |
| // policy. |
| // We can either wrap a symbolic ErrorCode (i.e. ERR_XXX enum values), an |
| // errno value (in the range 1..4095), a pointer to a TrapFnc callback |
| // handling a SECCOMP_RET_TRAP trap, or a complex constraint. |
| // All of the commonly used values are stored in the "err_" field. So, code |
| // that is using the ErrorCode class typically operates on a single 32bit |
| // field. |
| class ErrorCode { |
| public: |
| enum { |
| // Allow this system call. |
| ERR_ALLOWED = 0x0000, |
| |
| // Deny the system call with a particular "errno" value. |
| ERR_MIN_ERRNO = 1, |
| ERR_MAX_ERRNO = 4095, |
| |
| // This code should never be used directly, it is used internally only. |
| ERR_INVALID = -1, |
| }; |
| |
| // TrapFnc is a pointer to a function that handles Seccomp traps in |
| // user-space. The seccomp policy can request that a trap handler gets |
| // installed; it does so by returning a suitable ErrorCode() from the |
| // syscallEvaluator. See the ErrorCode() constructor for how to pass in |
| // the function pointer. |
| // Please note that TrapFnc is executed from signal context and must be |
| // async-signal safe: |
| // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html |
| typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); |
| |
| enum ArgType { |
| TP_32BIT, TP_64BIT, |
| }; |
| |
| enum Operation { |
| OP_EQUAL, OP_GREATER, OP_GREATER_EQUAL, OP_HAS_BITS, |
| OP_NUM_OPS, |
| }; |
| |
| // We allow the default constructor, as it makes the ErrorCode class |
| // much easier to use. But if we ever encounter an invalid ErrorCode |
| // when compiling a BPF filter, we deliberately generate an invalid |
| // program that will get flagged both by our Verifier class and by |
| // the Linux kernel. |
| ErrorCode() : |
| error_type_(ET_INVALID), |
| err_(SECCOMP_RET_INVALID) { |
| } |
| explicit ErrorCode(int err); |
| |
| // For all practical purposes, ErrorCodes are treated as if they were |
| // structs. The copy constructor and assignment operator are trivial and |
| // we do not need to explicitly specify them. |
| // Most notably, it is in fact perfectly OK to directly copy the passed_ and |
| // failed_ field. They only ever get set by our private constructor, and the |
| // callers handle life-cycle management for these objects. |
| |
| // Destructor |
| ~ErrorCode() { } |
| |
| bool Equals(const ErrorCode& err) const; |
| bool LessThan(const ErrorCode& err) const; |
| |
| uint32_t err() const { return err_; } |
| |
| struct LessThan { |
| bool operator()(const ErrorCode& a, const ErrorCode& b) const { |
| return a.LessThan(b); |
| } |
| }; |
| |
| private: |
| friend class Sandbox; |
| friend class Verifier; |
| |
| enum ErrorType { |
| ET_INVALID, ET_SIMPLE, ET_TRAP, ET_COND, |
| }; |
| |
| // If we are wrapping a callback, we must assign a unique id. This id is |
| // how the kernel tells us which one of our different SECCOMP_RET_TRAP |
| // cases has been triggered. |
| ErrorCode(TrapFnc fnc, const void *aux, uint16_t id); |
| |
| // Some system calls require inspection of arguments. This constructor |
| // allows us to specify additional constraints. |
| ErrorCode(int argno, ArgType width, Operation op, uint64_t value, |
| const ErrorCode *passed, const ErrorCode *failed); |
| |
| ErrorType error_type_; |
| |
| union { |
| // Fields needed for SECCOMP_RET_TRAP callbacks |
| struct { |
| TrapFnc fnc_; // Callback function and arg, if trap was |
| void *aux_; // triggered by the kernel's BPF filter. |
| }; |
| |
| // Fields needed when inspecting additional arguments. |
| struct { |
| uint64_t value_; // Value that we are comparing with. |
| int argno_; // Syscall arg number that we are inspecting. |
| ArgType width_; // Whether we are looking at a 32/64bit value. |
| Operation op_; // Comparison operation. |
| const ErrorCode *passed_; // Value to be returned if comparison passed, |
| const ErrorCode *failed_; // or if it failed. |
| }; |
| }; |
| |
| // 32bit field used for all possible types of ErrorCode values. This is |
| // the value that uniquely identifies any ErrorCode and it (typically) can |
| // be emitted directly into a BPF filter program. |
| uint32_t err_; |
| |
| }; |
| |
| } // namespace |
| |
| #endif // SANDBOX_LINUX_SECCOMP_BPF_ERRORCODE_H__ |