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 <limits> 10 11#include "base/logging.h" 12#include "base/memory/ref_counted.h" 13#include "sandbox/linux/seccomp-bpf/errorcode.h" 14#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 15 16namespace sandbox { 17namespace bpf_dsl { 18namespace { 19 20class AllowResultExprImpl : public internal::ResultExprImpl { 21 public: 22 AllowResultExprImpl() {} 23 24 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 25 return ErrorCode(ErrorCode::ERR_ALLOWED); 26 } 27 28 private: 29 virtual ~AllowResultExprImpl() {} 30 31 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl); 32}; 33 34class ErrorResultExprImpl : public internal::ResultExprImpl { 35 public: 36 explicit ErrorResultExprImpl(int err) : err_(err) { 37 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO); 38 } 39 40 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 41 return ErrorCode(err_); 42 } 43 44 private: 45 virtual ~ErrorResultExprImpl() {} 46 47 int err_; 48 49 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl); 50}; 51 52class KillResultExprImpl : public internal::ResultExprImpl { 53 public: 54 explicit KillResultExprImpl(const char* msg) : msg_(msg) { DCHECK(msg_); } 55 56 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 57 return sb->Kill(msg_); 58 } 59 60 private: 61 virtual ~KillResultExprImpl() {} 62 63 const char* msg_; 64 65 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl); 66}; 67 68class TraceResultExprImpl : public internal::ResultExprImpl { 69 public: 70 TraceResultExprImpl(uint16_t aux) : aux_(aux) {} 71 72 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 73 return ErrorCode(ErrorCode::ERR_TRACE + aux_); 74 } 75 76 private: 77 virtual ~TraceResultExprImpl() {} 78 79 uint16_t aux_; 80 81 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl); 82}; 83 84class TrapResultExprImpl : public internal::ResultExprImpl { 85 public: 86 TrapResultExprImpl(Trap::TrapFnc func, const void* arg) 87 : func_(func), arg_(arg) { 88 DCHECK(func_); 89 } 90 91 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 92 return sb->Trap(func_, arg_); 93 } 94 95 private: 96 virtual ~TrapResultExprImpl() {} 97 98 Trap::TrapFnc func_; 99 const void* arg_; 100 101 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl); 102}; 103 104class UnsafeTrapResultExprImpl : public internal::ResultExprImpl { 105 public: 106 UnsafeTrapResultExprImpl(Trap::TrapFnc func, const void* arg) 107 : func_(func), arg_(arg) { 108 DCHECK(func_); 109 } 110 111 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 112 return sb->UnsafeTrap(func_, arg_); 113 } 114 115 private: 116 virtual ~UnsafeTrapResultExprImpl() {} 117 118 Trap::TrapFnc func_; 119 const void* arg_; 120 121 DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl); 122}; 123 124class IfThenResultExprImpl : public internal::ResultExprImpl { 125 public: 126 IfThenResultExprImpl(const BoolExpr& cond, 127 const ResultExpr& then_result, 128 const ResultExpr& else_result) 129 : cond_(cond), then_result_(then_result), else_result_(else_result) {} 130 131 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { 132 return cond_->Compile( 133 sb, then_result_->Compile(sb), else_result_->Compile(sb)); 134 } 135 136 private: 137 virtual ~IfThenResultExprImpl() {} 138 139 BoolExpr cond_; 140 ResultExpr then_result_; 141 ResultExpr else_result_; 142 143 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl); 144}; 145 146class ConstBoolExprImpl : public internal::BoolExprImpl { 147 public: 148 ConstBoolExprImpl(bool value) : value_(value) {} 149 150 virtual ErrorCode Compile(SandboxBPF* sb, 151 ErrorCode true_ec, 152 ErrorCode false_ec) const OVERRIDE { 153 return value_ ? true_ec : false_ec; 154 } 155 156 private: 157 virtual ~ConstBoolExprImpl() {} 158 159 bool value_; 160 161 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl); 162}; 163 164class PrimitiveBoolExprImpl : public internal::BoolExprImpl { 165 public: 166 PrimitiveBoolExprImpl(int argno, 167 ErrorCode::ArgType is_32bit, 168 uint64_t mask, 169 uint64_t value) 170 : argno_(argno), is_32bit_(is_32bit), mask_(mask), value_(value) {} 171 172 virtual ErrorCode Compile(SandboxBPF* sb, 173 ErrorCode true_ec, 174 ErrorCode false_ec) const OVERRIDE { 175 return sb->CondMaskedEqual( 176 argno_, is_32bit_, mask_, value_, true_ec, false_ec); 177 } 178 179 private: 180 virtual ~PrimitiveBoolExprImpl() {} 181 182 int argno_; 183 ErrorCode::ArgType is_32bit_; 184 uint64_t mask_; 185 uint64_t value_; 186 187 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl); 188}; 189 190class NegateBoolExprImpl : public internal::BoolExprImpl { 191 public: 192 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {} 193 194 virtual ErrorCode Compile(SandboxBPF* sb, 195 ErrorCode true_ec, 196 ErrorCode false_ec) const OVERRIDE { 197 return cond_->Compile(sb, false_ec, true_ec); 198 } 199 200 private: 201 virtual ~NegateBoolExprImpl() {} 202 203 BoolExpr cond_; 204 205 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl); 206}; 207 208class AndBoolExprImpl : public internal::BoolExprImpl { 209 public: 210 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) 211 : lhs_(lhs), rhs_(rhs) {} 212 213 virtual ErrorCode Compile(SandboxBPF* sb, 214 ErrorCode true_ec, 215 ErrorCode false_ec) const OVERRIDE { 216 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec); 217 } 218 219 private: 220 virtual ~AndBoolExprImpl() {} 221 222 BoolExpr lhs_; 223 BoolExpr rhs_; 224 225 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); 226}; 227 228class OrBoolExprImpl : public internal::BoolExprImpl { 229 public: 230 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) 231 : lhs_(lhs), rhs_(rhs) {} 232 233 virtual ErrorCode Compile(SandboxBPF* sb, 234 ErrorCode true_ec, 235 ErrorCode false_ec) const OVERRIDE { 236 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec)); 237 } 238 239 private: 240 virtual ~OrBoolExprImpl() {} 241 242 BoolExpr lhs_; 243 BoolExpr rhs_; 244 245 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); 246}; 247 248} // namespace 249 250namespace internal { 251 252uint64_t DefaultMask(size_t size) { 253 switch (size) { 254 case 4: 255 return std::numeric_limits<uint32_t>::max(); 256 case 8: 257 return std::numeric_limits<uint64_t>::max(); 258 default: 259 CHECK(false) << "Unimplemented DefaultMask case"; 260 return 0; 261 } 262} 263 264BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) { 265 CHECK(size == 4 || size == 8); 266 267 // TODO(mdempsky): Should we just always use TP_64BIT? 268 const ErrorCode::ArgType arg_type = 269 (size == 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; 270 271 return BoolExpr(new const PrimitiveBoolExprImpl(num, arg_type, mask, val)); 272} 273 274} // namespace internal 275 276ResultExpr Allow() { 277 return ResultExpr(new const AllowResultExprImpl()); 278} 279 280ResultExpr Error(int err) { 281 return ResultExpr(new const ErrorResultExprImpl(err)); 282} 283 284ResultExpr Kill(const char* msg) { 285 return ResultExpr(new const KillResultExprImpl(msg)); 286} 287 288ResultExpr Trace(uint16_t aux) { 289 return ResultExpr(new const TraceResultExprImpl(aux)); 290} 291 292ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux) { 293 return ResultExpr(new const TrapResultExprImpl(trap_func, aux)); 294} 295 296ResultExpr UnsafeTrap(Trap::TrapFnc trap_func, const void* aux) { 297 return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func, aux)); 298} 299 300BoolExpr BoolConst(bool value) { 301 return BoolExpr(new const ConstBoolExprImpl(value)); 302} 303 304BoolExpr operator!(const BoolExpr& cond) { 305 return BoolExpr(new const NegateBoolExprImpl(cond)); 306} 307 308BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs) { 309 return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); 310} 311 312BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs) { 313 return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); 314} 315 316Elser If(const BoolExpr& cond, const ResultExpr& then_result) { 317 return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result); 318} 319 320Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) { 321} 322 323Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) { 324} 325 326Elser::~Elser() { 327} 328 329Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const { 330 return Elser( 331 Cons<Clause>::Make(std::make_pair(cond, then_result), clause_list_)); 332} 333 334ResultExpr Elser::Else(const ResultExpr& else_result) const { 335 // We finally have the default result expression for this 336 // if/then/else sequence. Also, we've already accumulated all 337 // if/then pairs into a list of reverse order (i.e., lower priority 338 // conditions are listed before higher priority ones). E.g., an 339 // expression like 340 // 341 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4) 342 // 343 // will have built up a list like 344 // 345 // [(b3, e3), (b2, e2), (b1, e1)]. 346 // 347 // Now that we have e4, we can walk the list and create a ResultExpr 348 // tree like: 349 // 350 // expr = e4 351 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) 352 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) 353 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) 354 // 355 // and end up with an appropriately chained tree. 356 357 ResultExpr expr = else_result; 358 for (Cons<Clause>::List it = clause_list_; it.get(); it = it->tail()) { 359 Clause clause = it->head(); 360 expr = ResultExpr( 361 new const IfThenResultExprImpl(clause.first, clause.second, expr)); 362 } 363 return expr; 364} 365 366ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const { 367 return Error(ENOSYS); 368} 369 370ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb, 371 int sysno) const { 372 return EvaluateSyscall(sysno)->Compile(sb); 373} 374 375ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const { 376 return InvalidSyscall()->Compile(sb); 377} 378 379ResultExpr SandboxBPFDSLPolicy::Trap(Trap::TrapFnc trap_func, const void* aux) { 380 return bpf_dsl::Trap(trap_func, aux); 381} 382 383} // namespace bpf_dsl 384} // namespace sandbox 385