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