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