summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp-bpf/errorcode.h
blob: d2661dbd066eb399369e24d4db050c332ee0fb90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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 CodeGen;
  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, bool safe, 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.
      bool    safe_;             // Keep sandbox active while calling fnc_()
    };

    // 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__