Home | History | Annotate | Download | only in bpf_dsl
      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 
     16 namespace sandbox {
     17 namespace bpf_dsl {
     18 namespace {
     19 
     20 class 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 
     34 class 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 
     52 class 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 
     68 class 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 
     84 class 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 
    104 class 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 
    124 class 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 
    146 class 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 
    164 class 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 
    190 class 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 
    208 class 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 
    228 class 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 
    250 namespace internal {
    251 
    252 uint64_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 
    264 BoolExpr 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 
    276 ResultExpr Allow() {
    277   return ResultExpr(new const AllowResultExprImpl());
    278 }
    279 
    280 ResultExpr Error(int err) {
    281   return ResultExpr(new const ErrorResultExprImpl(err));
    282 }
    283 
    284 ResultExpr Kill(const char* msg) {
    285   return ResultExpr(new const KillResultExprImpl(msg));
    286 }
    287 
    288 ResultExpr Trace(uint16_t aux) {
    289   return ResultExpr(new const TraceResultExprImpl(aux));
    290 }
    291 
    292 ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux) {
    293   return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
    294 }
    295 
    296 ResultExpr UnsafeTrap(Trap::TrapFnc trap_func, const void* aux) {
    297   return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func, aux));
    298 }
    299 
    300 BoolExpr BoolConst(bool value) {
    301   return BoolExpr(new const ConstBoolExprImpl(value));
    302 }
    303 
    304 BoolExpr operator!(const BoolExpr& cond) {
    305   return BoolExpr(new const NegateBoolExprImpl(cond));
    306 }
    307 
    308 BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs) {
    309   return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
    310 }
    311 
    312 BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs) {
    313   return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
    314 }
    315 
    316 Elser If(const BoolExpr& cond, const ResultExpr& then_result) {
    317   return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result);
    318 }
    319 
    320 Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) {
    321 }
    322 
    323 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
    324 }
    325 
    326 Elser::~Elser() {
    327 }
    328 
    329 Elser 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 
    334 ResultExpr 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 
    366 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
    367   return Error(ENOSYS);
    368 }
    369 
    370 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
    371                                                int sysno) const {
    372   return EvaluateSyscall(sysno)->Compile(sb);
    373 }
    374 
    375 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
    376   return InvalidSyscall()->Compile(sb);
    377 }
    378 
    379 ResultExpr 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