OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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/bpf_dsl/bpf_dsl.h" |
| 6 |
| 7 #include <errno.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/memory/ref_counted.h" |
| 11 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 12 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 13 |
| 14 using namespace sandbox::bpf_dsl::internal; |
| 15 typedef ::sandbox::Trap::TrapFnc TrapFnc; |
| 16 |
| 17 namespace sandbox { |
| 18 namespace bpf_dsl { |
| 19 namespace { |
| 20 |
| 21 class AllowResultExprImpl : public ResultExprImpl { |
| 22 public: |
| 23 AllowResultExprImpl() {} |
| 24 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
| 25 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 26 } |
| 27 |
| 28 private: |
| 29 virtual ~AllowResultExprImpl() {} |
| 30 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl); |
| 31 }; |
| 32 |
| 33 class ErrorResultExprImpl : public ResultExprImpl { |
| 34 public: |
| 35 explicit ErrorResultExprImpl(int err) : err_(err) { |
| 36 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO); |
| 37 } |
| 38 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
| 39 return ErrorCode(err_); |
| 40 } |
| 41 |
| 42 private: |
| 43 virtual ~ErrorResultExprImpl() {} |
| 44 int err_; |
| 45 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl); |
| 46 }; |
| 47 |
| 48 class TrapResultExprImpl : public ResultExprImpl { |
| 49 public: |
| 50 TrapResultExprImpl(TrapFnc func, void* arg) : func_(func), arg_(arg) { |
| 51 DCHECK(func_); |
| 52 } |
| 53 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
| 54 return sb->Trap(func_, arg_); |
| 55 } |
| 56 |
| 57 private: |
| 58 virtual ~TrapResultExprImpl() {} |
| 59 TrapFnc func_; |
| 60 void* arg_; |
| 61 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl); |
| 62 }; |
| 63 |
| 64 class IfThenResultExprImpl : public ResultExprImpl { |
| 65 public: |
| 66 IfThenResultExprImpl(BoolExpr cond, |
| 67 ResultExpr then_result, |
| 68 ResultExpr else_result) |
| 69 : cond_(cond), then_result_(then_result), else_result_(else_result) {} |
| 70 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
| 71 return cond_->Compile( |
| 72 sb, then_result_->Compile(sb), else_result_->Compile(sb)); |
| 73 } |
| 74 |
| 75 private: |
| 76 virtual ~IfThenResultExprImpl() {} |
| 77 BoolExpr cond_; |
| 78 ResultExpr then_result_; |
| 79 ResultExpr else_result_; |
| 80 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl); |
| 81 }; |
| 82 |
| 83 class PrimitiveBoolExprImpl : public BoolExprImpl { |
| 84 public: |
| 85 PrimitiveBoolExprImpl(int argno, |
| 86 ErrorCode::ArgType is_32bit, |
| 87 ErrorCode::Operation op, |
| 88 uint64_t value) |
| 89 : argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {} |
| 90 virtual ErrorCode Compile(SandboxBPF* sb, |
| 91 ErrorCode true_ec, |
| 92 ErrorCode false_ec) const OVERRIDE { |
| 93 return sb->Cond(argno_, is_32bit_, op_, value_, true_ec, false_ec); |
| 94 } |
| 95 |
| 96 private: |
| 97 virtual ~PrimitiveBoolExprImpl() {} |
| 98 int argno_; |
| 99 ErrorCode::ArgType is_32bit_; |
| 100 ErrorCode::Operation op_; |
| 101 uint64_t value_; |
| 102 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl); |
| 103 }; |
| 104 |
| 105 class NegateBoolExprImpl : public BoolExprImpl { |
| 106 public: |
| 107 explicit NegateBoolExprImpl(BoolExpr cond) : cond_(cond) {} |
| 108 virtual ErrorCode Compile(SandboxBPF* sb, |
| 109 ErrorCode true_ec, |
| 110 ErrorCode false_ec) const OVERRIDE { |
| 111 return cond_->Compile(sb, false_ec, true_ec); |
| 112 } |
| 113 |
| 114 private: |
| 115 virtual ~NegateBoolExprImpl() {} |
| 116 BoolExpr cond_; |
| 117 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl); |
| 118 }; |
| 119 |
| 120 class AndBoolExprImpl : public BoolExprImpl { |
| 121 public: |
| 122 AndBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {} |
| 123 virtual ErrorCode Compile(SandboxBPF* sb, |
| 124 ErrorCode true_ec, |
| 125 ErrorCode false_ec) const OVERRIDE { |
| 126 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec); |
| 127 } |
| 128 |
| 129 private: |
| 130 virtual ~AndBoolExprImpl() {} |
| 131 BoolExpr lhs_, rhs_; |
| 132 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); |
| 133 }; |
| 134 |
| 135 class OrBoolExprImpl : public BoolExprImpl { |
| 136 public: |
| 137 OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {} |
| 138 virtual ErrorCode Compile(SandboxBPF* sb, |
| 139 ErrorCode true_ec, |
| 140 ErrorCode false_ec) const OVERRIDE { |
| 141 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec)); |
| 142 } |
| 143 |
| 144 private: |
| 145 virtual ~OrBoolExprImpl() {} |
| 146 BoolExpr lhs_, rhs_; |
| 147 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); |
| 148 }; |
| 149 |
| 150 } // namespace |
| 151 |
| 152 namespace internal { |
| 153 |
| 154 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) { |
| 155 CHECK(num >= 0 && num < 6); |
| 156 CHECK(size >= 1 && size <= 8); |
| 157 CHECK_NE(0U, mask) << "zero mask doesn't make sense"; |
| 158 CHECK_EQ(val, val & mask) << "val contains masked out bits"; |
| 159 |
| 160 // TODO(mdempsky): Should we just always use TP_64BIT? |
| 161 const ErrorCode::ArgType arg_type = |
| 162 (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; |
| 163 |
| 164 if (mask == static_cast<uint64_t>(-1)) { |
| 165 // Arg == Val |
| 166 return BoolExpr(new const PrimitiveBoolExprImpl( |
| 167 num, arg_type, ErrorCode::OP_EQUAL, val)); |
| 168 } else if (mask == val) { |
| 169 // (Arg & Mask) == Mask |
| 170 return BoolExpr(new const PrimitiveBoolExprImpl( |
| 171 num, arg_type, ErrorCode::OP_HAS_ALL_BITS, mask)); |
| 172 } else if (val == 0) { |
| 173 // (Arg & Mask) == 0, which is semantically equivalent to !((arg & mask) != |
| 174 // 0). |
| 175 return !BoolExpr(new const PrimitiveBoolExprImpl( |
| 176 num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask)); |
| 177 } else { |
| 178 CHECK(false) << "Unimplemented ArgEq case"; |
| 179 return BoolExpr(); |
| 180 } |
| 181 } |
| 182 |
| 183 } // namespace internal |
| 184 |
| 185 ResultExpr Allow() { |
| 186 return ResultExpr(new const AllowResultExprImpl()); |
| 187 } |
| 188 |
| 189 ResultExpr Error(int err) { |
| 190 return ResultExpr(new const ErrorResultExprImpl(err)); |
| 191 } |
| 192 |
| 193 ResultExpr Trap(TrapFnc trap_func, void* aux) { |
| 194 return ResultExpr(new const TrapResultExprImpl(trap_func, aux)); |
| 195 } |
| 196 |
| 197 BoolExpr operator!(BoolExpr cond) { |
| 198 return BoolExpr(new const NegateBoolExprImpl(cond)); |
| 199 } |
| 200 |
| 201 BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) { |
| 202 return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); |
| 203 } |
| 204 |
| 205 BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) { |
| 206 return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); |
| 207 } |
| 208 |
| 209 Elser If(BoolExpr cond, ResultExpr then_result) { |
| 210 return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result); |
| 211 } |
| 212 |
| 213 Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) { |
| 214 } |
| 215 |
| 216 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) { |
| 217 } |
| 218 |
| 219 Elser::~Elser() { |
| 220 } |
| 221 |
| 222 Elser Elser::ElseIf(BoolExpr cond, ResultExpr then_result) const { |
| 223 return Elser( |
| 224 Cons<Clause>::Make(std::make_pair(cond, then_result), clause_list_)); |
| 225 } |
| 226 |
| 227 ResultExpr Elser::Else(ResultExpr else_result) const { |
| 228 // We finally have the default result expression for this |
| 229 // if/then/else sequence. Also, we've already accumulated all |
| 230 // if/then pairs into a list of reverse order (i.e., lower priority |
| 231 // conditions are listed before higher priority ones). E.g., an |
| 232 // expression like |
| 233 // |
| 234 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4) |
| 235 // |
| 236 // will have built up a list like |
| 237 // |
| 238 // [(b3, e3), (b2, e2), (b1, e1)]. |
| 239 // |
| 240 // Now that we have e4, we can walk the list and create a ResultExpr |
| 241 // tree like: |
| 242 // |
| 243 // expr = e4 |
| 244 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) |
| 245 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) |
| 246 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) |
| 247 // |
| 248 // and end up with an appropriately chained tree. |
| 249 |
| 250 ResultExpr expr = else_result; |
| 251 for (Cons<Clause>::List it = clause_list_; it; it = it->tail()) { |
| 252 Clause clause = it->head(); |
| 253 expr = ResultExpr( |
| 254 new const IfThenResultExprImpl(clause.first, clause.second, expr)); |
| 255 } |
| 256 return expr; |
| 257 } |
| 258 |
| 259 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const { |
| 260 return Error(ENOSYS); |
| 261 } |
| 262 |
| 263 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb, |
| 264 int sysno) const { |
| 265 return EvaluateSyscall(sysno)->Compile(sb); |
| 266 } |
| 267 |
| 268 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const { |
| 269 return InvalidSyscall()->Compile(sb); |
| 270 } |
| 271 |
| 272 ResultExpr SandboxBPFDSLPolicy::Trap(::sandbox::Trap::TrapFnc trap_func, |
| 273 void* aux) { |
| 274 return bpf_dsl::Trap(trap_func, aux); |
| 275 } |
| 276 |
| 277 } // namespace bpf_dsl |
| 278 } // namespace sandbox |
OLD | NEW |