1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "sandbox/linux/seccomp-bpf/errorcode.h"
6
7#include "sandbox/linux/seccomp-bpf/die.h"
8#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
9
10namespace sandbox {
11
12ErrorCode::ErrorCode() : error_type_(ET_INVALID), err_(SECCOMP_RET_INVALID) {
13}
14
15ErrorCode::ErrorCode(int err) {
16  switch (err) {
17    case ERR_ALLOWED:
18      err_ = SECCOMP_RET_ALLOW;
19      error_type_ = ET_SIMPLE;
20      break;
21    case ERR_MIN_ERRNO... ERR_MAX_ERRNO:
22      err_ = SECCOMP_RET_ERRNO + err;
23      error_type_ = ET_SIMPLE;
24      break;
25    default:
26      if ((err & ~SECCOMP_RET_DATA) == ERR_TRACE) {
27        err_ = SECCOMP_RET_TRACE + (err & SECCOMP_RET_DATA);
28        error_type_ = ET_SIMPLE;
29        break;
30      }
31      SANDBOX_DIE("Invalid use of ErrorCode object");
32  }
33}
34
35ErrorCode::ErrorCode(Trap::TrapFnc fnc, const void* aux, bool safe)
36    : error_type_(ET_TRAP),
37      fnc_(fnc),
38      aux_(const_cast<void*>(aux)),
39      safe_(safe),
40      err_(SECCOMP_RET_TRAP + Trap::MakeTrap(fnc, aux, safe)) {
41}
42
43ErrorCode::ErrorCode(int argno,
44                     ArgType width,
45                     uint64_t mask,
46                     uint64_t value,
47                     const ErrorCode* passed,
48                     const ErrorCode* failed)
49    : error_type_(ET_COND),
50      mask_(mask),
51      value_(value),
52      argno_(argno),
53      width_(width),
54      passed_(passed),
55      failed_(failed),
56      err_(SECCOMP_RET_INVALID) {
57}
58
59bool ErrorCode::Equals(const ErrorCode& err) const {
60  if (error_type_ == ET_INVALID || err.error_type_ == ET_INVALID) {
61    SANDBOX_DIE("Dereferencing invalid ErrorCode");
62  }
63  if (error_type_ != err.error_type_) {
64    return false;
65  }
66  if (error_type_ == ET_SIMPLE || error_type_ == ET_TRAP) {
67    return err_ == err.err_;
68  } else if (error_type_ == ET_COND) {
69    return mask_ == err.mask_ && value_ == err.value_ && argno_ == err.argno_ &&
70           width_ == err.width_ && passed_->Equals(*err.passed_) &&
71           failed_->Equals(*err.failed_);
72  } else {
73    SANDBOX_DIE("Corrupted ErrorCode");
74  }
75}
76
77bool ErrorCode::LessThan(const ErrorCode& err) const {
78  // Implementing a "LessThan()" operator allows us to use ErrorCode objects
79  // as keys in STL containers; most notably, it also allows us to put them
80  // into std::set<>. Actual ordering is not important as long as it is
81  // deterministic.
82  if (error_type_ == ET_INVALID || err.error_type_ == ET_INVALID) {
83    SANDBOX_DIE("Dereferencing invalid ErrorCode");
84  }
85  if (error_type_ != err.error_type_) {
86    return error_type_ < err.error_type_;
87  } else {
88    if (error_type_ == ET_SIMPLE || error_type_ == ET_TRAP) {
89      return err_ < err.err_;
90    } else if (error_type_ == ET_COND) {
91      if (mask_ != err.mask_) {
92        return mask_ < err.mask_;
93      } else if (value_ != err.value_) {
94        return value_ < err.value_;
95      } else if (argno_ != err.argno_) {
96        return argno_ < err.argno_;
97      } else if (width_ != err.width_) {
98        return width_ < err.width_;
99      } else if (!passed_->Equals(*err.passed_)) {
100        return passed_->LessThan(*err.passed_);
101      } else if (!failed_->Equals(*err.failed_)) {
102        return failed_->LessThan(*err.failed_);
103      } else {
104        return false;
105      }
106    } else {
107      SANDBOX_DIE("Corrupted ErrorCode");
108    }
109  }
110}
111
112}  // namespace sandbox
113