OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h" | 5 #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 9 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
10 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 10 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
11 | 11 |
| 12 using namespace sandbox::bpf_dsl::internal; |
| 13 |
12 namespace sandbox { | 14 namespace sandbox { |
13 | 15 |
14 namespace bpfdsl { | 16 namespace bpf_dsl { |
15 | 17 |
16 namespace { | 18 namespace { |
17 | 19 |
18 class BasicCondImpl : public CondImpl { | 20 class AllowResultExprImpl : public ResultExprImpl { |
19 public: | 21 public: |
20 BasicCondImpl(int argno, | 22 AllowResultExprImpl() {} |
21 ErrorCode::ArgType is_32bit, | 23 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
22 ErrorCode::Operation op, | 24 return ErrorCode(ErrorCode::ERR_ALLOWED); |
23 uint64_t value) | 25 } |
| 26 |
| 27 private: |
| 28 virtual ~AllowResultExprImpl() {} |
| 29 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl); |
| 30 }; |
| 31 |
| 32 class ErrorResultExprImpl : public ResultExprImpl { |
| 33 public: |
| 34 ErrorResultExprImpl(int err) : err_(err) { |
| 35 // TODO(mdempsky): Symbolic constants; tighter bounds check? |
| 36 CHECK(err_ >= 0 && err_ < 4096); |
| 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(TrapFunc 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 TrapFunc 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 PrimBoolExprImpl : public BoolExprImpl { |
| 84 public: |
| 85 PrimBoolExprImpl(int argno, |
| 86 ErrorCode::ArgType is_32bit, |
| 87 ErrorCode::Operation op, |
| 88 uint64_t value) |
24 : argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {} | 89 : argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {} |
25 virtual ErrorCode Compile(SandboxBPF* sb, | 90 virtual ErrorCode Compile(SandboxBPF* sb, |
26 ErrorCode true_ec, | 91 ErrorCode true_ec, |
27 ErrorCode false_ec) const OVERRIDE { | 92 ErrorCode false_ec) const OVERRIDE { |
28 return sb->Cond(argno_, is_32bit_, op_, value_, true_ec, false_ec); | 93 return sb->Cond(argno_, is_32bit_, op_, value_, true_ec, false_ec); |
29 } | 94 } |
30 | 95 |
31 private: | 96 private: |
32 virtual ~BasicCondImpl() {} | 97 virtual ~PrimBoolExprImpl() {} |
33 int argno_; | 98 int argno_; |
34 ErrorCode::ArgType is_32bit_; | 99 ErrorCode::ArgType is_32bit_; |
35 ErrorCode::Operation op_; | 100 ErrorCode::Operation op_; |
36 uint64_t value_; | 101 uint64_t value_; |
37 DISALLOW_COPY_AND_ASSIGN(BasicCondImpl); | 102 DISALLOW_COPY_AND_ASSIGN(PrimBoolExprImpl); |
38 }; | 103 }; |
39 | 104 |
40 class AndCondImpl : public CondImpl { | 105 class NegateBoolExprImpl : public BoolExprImpl { |
41 public: | 106 public: |
42 AndCondImpl(Cond lhs, Cond rhs) : lhs_(lhs), rhs_(rhs) {} | 107 NegateBoolExprImpl(BoolExpr cond) : cond_(cond) {} |
43 virtual ErrorCode Compile(SandboxBPF* sb, | 108 virtual ErrorCode Compile(SandboxBPF* sb, |
44 ErrorCode true_ec, | 109 ErrorCode true_ec, |
45 ErrorCode false_ec) const OVERRIDE { | 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 { |
46 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec); | 126 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec); |
47 } | 127 } |
48 | 128 |
49 private: | 129 private: |
50 virtual ~AndCondImpl() {} | 130 virtual ~AndBoolExprImpl() {} |
51 Cond lhs_, rhs_; | 131 BoolExpr lhs_, rhs_; |
52 DISALLOW_COPY_AND_ASSIGN(AndCondImpl); | 132 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); |
53 }; | 133 }; |
54 | 134 |
55 class OrCondImpl : public CondImpl { | 135 class OrBoolExprImpl : public BoolExprImpl { |
56 public: | 136 public: |
57 OrCondImpl(Cond lhs, Cond rhs) : lhs_(lhs), rhs_(rhs) {} | 137 OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {} |
58 virtual ErrorCode Compile(SandboxBPF* sb, | 138 virtual ErrorCode Compile(SandboxBPF* sb, |
59 ErrorCode true_ec, | 139 ErrorCode true_ec, |
60 ErrorCode false_ec) const OVERRIDE { | 140 ErrorCode false_ec) const OVERRIDE { |
61 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec)); | 141 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec)); |
62 } | 142 } |
63 | 143 |
64 private: | 144 private: |
65 virtual ~OrCondImpl() {} | 145 virtual ~OrBoolExprImpl() {} |
66 Cond lhs_, rhs_; | 146 BoolExpr lhs_, rhs_; |
67 DISALLOW_COPY_AND_ASSIGN(OrCondImpl); | 147 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); |
68 }; | 148 }; |
69 | 149 |
70 } // namespace | 150 } // namespace |
71 | 151 |
72 Cond operator&&(Cond lhs, Cond rhs) { | 152 namespace internal { |
73 return Cond(new AndCondImpl(lhs, rhs)); | 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(mask != 0) << "zero mask doesn't make sense"; |
| 158 const ErrorCode::ArgType arg_type = |
| 159 (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; |
| 160 if (mask == static_cast<uint64_t>(-1)) { |
| 161 return BoolExpr( |
| 162 new const PrimBoolExprImpl(num, arg_type, ErrorCode::OP_EQUAL, val)); |
| 163 } else if (mask == val) { |
| 164 return BoolExpr(new const PrimBoolExprImpl( |
| 165 num, arg_type, ErrorCode::OP_HAS_ALL_BITS, val)); |
| 166 } else if (val == 0) { |
| 167 // User asked for (arg & mask) == 0; we return !(arg & mask), |
| 168 // which is semantically equivalent. |
| 169 return !BoolExpr(new const PrimBoolExprImpl( |
| 170 num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask)); |
| 171 } else { |
| 172 NOTREACHED() << "Unsupported case"; |
| 173 return BoolExpr(); |
| 174 } |
74 } | 175 } |
75 | 176 |
76 Cond operator||(Cond lhs, Cond rhs) { | 177 IfThen::IfThen(BoolExpr cond_, ResultExpr then_, IfThenList rest_) |
77 return Cond(new OrCondImpl(lhs, rhs)); | 178 : cond(cond_), then(then_), rest(rest_) { |
78 } | 179 } |
79 | 180 |
80 Iffer::Iffer(SandboxBPF* sb) : sb_(sb) { | 181 IfThen::~IfThen() { |
81 DCHECK(sb); | |
82 } | 182 } |
83 | 183 |
84 Iffer::Iffer(const Iffer& iffer) : sb_(iffer.sb_) { | 184 } // namespace internal |
| 185 |
| 186 ResultExpr Allow() { |
| 187 return ResultExpr(new const AllowResultExprImpl()); |
85 } | 188 } |
86 | 189 |
87 Thener Iffer::If(Cond cond) const { | 190 ResultExpr Error(int err) { |
88 return Thener(sb_, cond); | 191 return ResultExpr(new const ErrorResultExprImpl(err)); |
89 } | 192 } |
90 | 193 |
91 Thener::Thener(SandboxBPF* sb, Cond cond) : sb_(sb), cond_(cond) { | 194 ResultExpr Trap(TrapFunc func, void* arg) { |
| 195 return ResultExpr(new const TrapResultExprImpl(func, arg)); |
| 196 } |
| 197 |
| 198 BoolExpr operator!(BoolExpr cond) { |
| 199 return BoolExpr(new const NegateBoolExprImpl(cond)); |
| 200 } |
| 201 |
| 202 BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) { |
| 203 return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); |
| 204 } |
| 205 |
| 206 BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) { |
| 207 return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); |
| 208 } |
| 209 |
| 210 Thener If(BoolExpr cond) { |
| 211 return Thener(IfThenList(), cond); |
| 212 } |
| 213 |
| 214 Thener::Thener(IfThenList if_then_list, BoolExpr cond) |
| 215 : if_then_list_(if_then_list), cond_(cond) { |
| 216 } |
| 217 |
| 218 Thener::Thener(const Thener& thener) |
| 219 : if_then_list_(thener.if_then_list_), cond_(thener.cond_) { |
92 } | 220 } |
93 | 221 |
94 Thener::~Thener() { | 222 Thener::~Thener() { |
95 } | 223 } |
96 | 224 |
97 Elser Thener::Then(ErrorCode true_ec) const { | 225 Elser Thener::Then(ResultExpr expr) const { |
98 return Elser(sb_, cond_, true_ec); | 226 return Elser(IfThen::Cons(cond_, expr, if_then_list_)); |
99 } | 227 } |
100 | 228 |
101 Elser::Elser(SandboxBPF* sb, Cond cond, ErrorCode true_ec) | 229 Elser::Elser(IfThenList if_then_list) : if_then_list_(if_then_list) { |
102 : sb_(sb), cond_(cond), true_ec_(true_ec) { | 230 } |
| 231 |
| 232 Elser::Elser(const Elser& elser) : if_then_list_(elser.if_then_list_) { |
103 } | 233 } |
104 | 234 |
105 Elser::~Elser() { | 235 Elser::~Elser() { |
106 } | 236 } |
107 | 237 |
108 ErrorCode Elser::Else(ErrorCode false_ec) const { | 238 ResultExpr Elser::Else(ResultExpr expr) const { |
109 return cond_->Compile(sb_, true_ec_, false_ec); | 239 // We finally have the default result expression for this |
| 240 // if/then/else sequence. Also, we've already accumulated all |
| 241 // if/then pairs into a list of reverse order (i.e., lower priority |
| 242 // conditions are listed before higher priority ones). E.g., an |
| 243 // expression like |
| 244 // |
| 245 // If(b1).Then(e1).ElseIf(b2).Then(e2).ElseIf(b3).Then(e3).Else(e4) |
| 246 // |
| 247 // will have built up a list like |
| 248 // |
| 249 // [(b3, e3), (b2, e2), (b1, e1)]. |
| 250 // |
| 251 // Now that we have e4, we can walk the list and create a ResultExpr |
| 252 // tree like: |
| 253 // |
| 254 // expr = e4 |
| 255 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) |
| 256 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) |
| 257 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) |
| 258 // |
| 259 // and end up with an appropriately chained tree. |
| 260 |
| 261 for (IfThenList it = if_then_list_; it; it = it->rest) { |
| 262 expr = ResultExpr(new const IfThenResultExprImpl(it->cond, it->then, expr)); |
| 263 } |
| 264 return expr; |
110 } | 265 } |
111 | 266 |
112 } // namespace bpfdsl | 267 Thener Elser::ElseIf(BoolExpr expr) const { |
113 | 268 return Thener(if_then_list_, expr); |
114 bpfdsl::Iffer DSL(SandboxBPF* sb) { | |
115 return bpfdsl::Iffer(sb); | |
116 } | 269 } |
117 | 270 |
118 template <typename T> | 271 ErrorCode SandboxBPFPolicyDSL::EvaluateSyscall(SandboxBPF* sb, |
119 Arg<T>::Arg(int num) | 272 int sysno) const { |
120 : num_(num) { | 273 return EvaluateSyscall(sysno)->Compile(sb); |
121 DCHECK(num >= 0 && num < 6); | |
122 } | 274 } |
123 | 275 |
124 template <typename T> | 276 ErrorCode SandboxBPFPolicyDSL::InvalidSyscall(SandboxBPF* sb) const { |
125 bpfdsl::Cond Arg<T>::operator==(const T& rhs) const { | 277 return InvalidSyscall()->Compile(sb); |
126 const ErrorCode::ArgType arg_type = | |
127 (sizeof(T) <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; | |
128 return bpfdsl::Cond( | |
129 new bpfdsl::BasicCondImpl(num_, arg_type, ErrorCode::OP_EQUAL, rhs)); | |
130 } | 278 } |
131 | 279 |
132 template class Arg<int>; | 280 ResultExpr SandboxBPFPolicyDSL::InvalidSyscall() const { |
| 281 return Error(ENOSYS); |
| 282 } |
| 283 |
| 284 } // namespace bpf_dsl |
133 | 285 |
134 } // sandbox | 286 } // sandbox |
OLD | NEW |