Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: sandbox/linux/bpf_dsl/policy_compiler.cc

Issue 944763004: Revert of bpf_dsl: switch PolicyCompiler from seccomp-bpf/die.h to base/logging.h (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sandbox/linux/bpf_dsl/trap_registry.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/bpf_dsl/policy_compiler.h" 5 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <linux/filter.h> 8 #include <linux/filter.h>
9 #include <sys/syscall.h> 9 #include <sys/syscall.h>
10 10
11 #include <limits> 11 #include <limits>
12 12
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" 15 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
16 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" 16 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
17 #include "sandbox/linux/bpf_dsl/codegen.h" 17 #include "sandbox/linux/bpf_dsl/codegen.h"
18 #include "sandbox/linux/bpf_dsl/policy.h" 18 #include "sandbox/linux/bpf_dsl/policy.h"
19 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" 19 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
20 #include "sandbox/linux/bpf_dsl/syscall_set.h" 20 #include "sandbox/linux/bpf_dsl/syscall_set.h"
21 #include "sandbox/linux/seccomp-bpf/die.h"
21 #include "sandbox/linux/seccomp-bpf/errorcode.h" 22 #include "sandbox/linux/seccomp-bpf/errorcode.h"
22 #include "sandbox/linux/system_headers/linux_seccomp.h" 23 #include "sandbox/linux/system_headers/linux_seccomp.h"
23 24
24 namespace sandbox { 25 namespace sandbox {
25 namespace bpf_dsl { 26 namespace bpf_dsl {
26 27
27 namespace { 28 namespace {
28 29
29 #if defined(__i386__) || defined(__x86_64__) 30 #if defined(__i386__) || defined(__x86_64__)
30 const bool kIsIntel = true; 31 const bool kIsIntel = true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 conds_(), 89 conds_(),
89 gen_(), 90 gen_(),
90 has_unsafe_traps_(HasUnsafeTraps(policy_)) { 91 has_unsafe_traps_(HasUnsafeTraps(policy_)) {
91 DCHECK(policy); 92 DCHECK(policy);
92 } 93 }
93 94
94 PolicyCompiler::~PolicyCompiler() { 95 PolicyCompiler::~PolicyCompiler() {
95 } 96 }
96 97
97 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() { 98 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() {
98 CHECK(policy_->InvalidSyscall()->IsDeny()) 99 if (!policy_->InvalidSyscall()->IsDeny()) {
99 << "Policies should deny invalid system calls"; 100 SANDBOX_DIE("Policies should deny invalid system calls.");
101 }
100 102
101 // If our BPF program has unsafe traps, enable support for them. 103 // If our BPF program has unsafe traps, enable support for them.
102 if (has_unsafe_traps_) { 104 if (has_unsafe_traps_) {
105 // As support for unsafe jumps essentially defeats all the security
106 // measures that the sandbox provides, we print a big warning message --
107 // and of course, we make sure to only ever enable this feature if it
108 // is actually requested by the sandbox policy.
109
103 CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC"; 110 CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC";
104 111
105 for (int sysnum : kSyscallsRequiredForUnsafeTraps) { 112 for (int sysnum : kSyscallsRequiredForUnsafeTraps) {
106 CHECK(policy_->EvaluateSyscall(sysnum)->IsAllow()) 113 if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) {
107 << "Policies that use UnsafeTrap() must unconditionally allow all " 114 SANDBOX_DIE(
108 "required system calls"; 115 "Policies that use UnsafeTrap() must unconditionally allow all "
116 "required system calls");
117 }
109 } 118 }
110 119
111 CHECK(registry_->EnableUnsafeTraps()) 120 if (!registry_->EnableUnsafeTraps()) {
112 << "We'd rather die than enable unsafe traps"; 121 // We should never be able to get here, as UnsafeTrap() should never
122 // actually return a valid ErrorCode object unless the user set the
123 // CHROME_SANDBOX_DEBUGGING environment variable; and therefore,
124 // "has_unsafe_traps" would always be false. But better double-check
125 // than enabling dangerous code.
126 SANDBOX_DIE("We'd rather die than enable unsafe traps");
127 }
113 } 128 }
114 129
115 // Assemble the BPF filter program. 130 // Assemble the BPF filter program.
116 scoped_ptr<CodeGen::Program> program(new CodeGen::Program()); 131 scoped_ptr<CodeGen::Program> program(new CodeGen::Program());
117 gen_.Compile(AssemblePolicy(), program.get()); 132 gen_.Compile(AssemblePolicy(), program.get());
118 return program.Pass(); 133 return program.Pass();
119 } 134 }
120 135
121 void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) { 136 void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) {
122 escapepc_ = escapepc; 137 escapepc_ = escapepc;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 254 }
240 ranges->push_back(Range{old_sysnum, old_node}); 255 ranges->push_back(Range{old_sysnum, old_node});
241 } 256 }
242 257
243 CodeGen::Node PolicyCompiler::AssembleJumpTable(Ranges::const_iterator start, 258 CodeGen::Node PolicyCompiler::AssembleJumpTable(Ranges::const_iterator start,
244 Ranges::const_iterator stop) { 259 Ranges::const_iterator stop) {
245 // We convert the list of system call ranges into jump table that performs 260 // We convert the list of system call ranges into jump table that performs
246 // a binary search over the ranges. 261 // a binary search over the ranges.
247 // As a sanity check, we need to have at least one distinct ranges for us 262 // As a sanity check, we need to have at least one distinct ranges for us
248 // to be able to build a jump table. 263 // to be able to build a jump table.
249 CHECK(start < stop) << "Invalid iterator range"; 264 if (stop - start <= 0) {
250 const auto n = stop - start; 265 SANDBOX_DIE("Invalid set of system call ranges");
251 if (n == 1) { 266 } else if (stop - start == 1) {
252 // If we have narrowed things down to a single range object, we can 267 // If we have narrowed things down to a single range object, we can
253 // return from the BPF filter program. 268 // return from the BPF filter program.
254 return start->node; 269 return start->node;
255 } 270 }
256 271
257 // Pick the range object that is located at the mid point of our list. 272 // Pick the range object that is located at the mid point of our list.
258 // We compare our system call number against the lowest valid system call 273 // We compare our system call number against the lowest valid system call
259 // number in this range object. If our number is lower, it is outside of 274 // number in this range object. If our number is lower, it is outside of
260 // this range object. If it is greater or equal, it might be inside. 275 // this range object. If it is greater or equal, it might be inside.
261 Ranges::const_iterator mid = start + n / 2; 276 Ranges::const_iterator mid = start + (stop - start) / 2;
262 277
263 // Sub-divide the list of ranges and continue recursively. 278 // Sub-divide the list of ranges and continue recursively.
264 CodeGen::Node jf = AssembleJumpTable(start, mid); 279 CodeGen::Node jf = AssembleJumpTable(start, mid);
265 CodeGen::Node jt = AssembleJumpTable(mid, stop); 280 CodeGen::Node jt = AssembleJumpTable(mid, stop);
266 return gen_.MakeInstruction(BPF_JMP + BPF_JGE + BPF_K, mid->from, jt, jf); 281 return gen_.MakeInstruction(BPF_JMP + BPF_JGE + BPF_K, mid->from, jt, jf);
267 } 282 }
268 283
269 CodeGen::Node PolicyCompiler::CompileResult(const ResultExpr& res) { 284 CodeGen::Node PolicyCompiler::CompileResult(const ResultExpr& res) {
270 return RetExpression(res->Compile(this)); 285 return RetExpression(res->Compile(this));
271 } 286 }
272 287
273 CodeGen::Node PolicyCompiler::RetExpression(const ErrorCode& err) { 288 CodeGen::Node PolicyCompiler::RetExpression(const ErrorCode& err) {
274 switch (err.error_type()) { 289 switch (err.error_type()) {
275 case ErrorCode::ET_COND: 290 case ErrorCode::ET_COND:
276 return CondExpression(err); 291 return CondExpression(err);
277 case ErrorCode::ET_SIMPLE: 292 case ErrorCode::ET_SIMPLE:
278 case ErrorCode::ET_TRAP: 293 case ErrorCode::ET_TRAP:
279 return gen_.MakeInstruction(BPF_RET + BPF_K, err.err()); 294 return gen_.MakeInstruction(BPF_RET + BPF_K, err.err());
280 default: 295 default:
281 LOG(FATAL) 296 SANDBOX_DIE("ErrorCode is not suitable for returning from a BPF program");
282 << "ErrorCode is not suitable for returning from a BPF program";
283 return CodeGen::kNullNode;
284 } 297 }
285 } 298 }
286 299
287 CodeGen::Node PolicyCompiler::CondExpression(const ErrorCode& cond) { 300 CodeGen::Node PolicyCompiler::CondExpression(const ErrorCode& cond) {
288 // Sanity check that |cond| makes sense. 301 // Sanity check that |cond| makes sense.
289 CHECK(cond.argno_ >= 0 && cond.argno_ < 6) << "Invalid argument number " 302 if (cond.argno_ < 0 || cond.argno_ >= 6) {
290 << cond.argno_; 303 SANDBOX_DIE("sandbox_bpf: invalid argument number");
291 CHECK(cond.width_ == ErrorCode::TP_32BIT ||
292 cond.width_ == ErrorCode::TP_64BIT)
293 << "Invalid argument width " << cond.width_;
294 CHECK_NE(0U, cond.mask_) << "Zero mask is invalid";
295 CHECK_EQ(cond.value_, cond.value_ & cond.mask_)
296 << "Value contains masked out bits";
297 if (sizeof(void*) == 4) {
298 CHECK_EQ(ErrorCode::TP_32BIT, cond.width_)
299 << "Invalid width on 32-bit platform";
300 } 304 }
301 if (cond.width_ == ErrorCode::TP_32BIT) { 305 if (cond.width_ != ErrorCode::TP_32BIT &&
302 CHECK_EQ(0U, cond.mask_ >> 32) << "Mask exceeds argument size"; 306 cond.width_ != ErrorCode::TP_64BIT) {
303 CHECK_EQ(0U, cond.value_ >> 32) << "Value exceeds argument size"; 307 SANDBOX_DIE("sandbox_bpf: invalid argument width");
304 } 308 }
309 if (cond.mask_ == 0) {
310 SANDBOX_DIE("sandbox_bpf: zero mask is invalid");
311 }
312 if ((cond.value_ & cond.mask_) != cond.value_) {
313 SANDBOX_DIE("sandbox_bpf: value contains masked out bits");
314 }
315 if (cond.width_ == ErrorCode::TP_32BIT &&
316 ((cond.mask_ >> 32) != 0 || (cond.value_ >> 32) != 0)) {
317 SANDBOX_DIE("sandbox_bpf: test exceeds argument size");
318 }
319 // TODO(mdempsky): Reject TP_64BIT on 32-bit platforms. For now we allow it
320 // because some SandboxBPF unit tests exercise it.
305 321
306 CodeGen::Node passed = RetExpression(*cond.passed_); 322 CodeGen::Node passed = RetExpression(*cond.passed_);
307 CodeGen::Node failed = RetExpression(*cond.failed_); 323 CodeGen::Node failed = RetExpression(*cond.failed_);
308 324
309 // We want to emit code to check "(arg & mask) == value" where arg, mask, and 325 // We want to emit code to check "(arg & mask) == value" where arg, mask, and
310 // value are 64-bit values, but the BPF machine is only 32-bit. We implement 326 // value are 64-bit values, but the BPF machine is only 32-bit. We implement
311 // this by independently testing the upper and lower 32-bits and continuing to 327 // this by independently testing the upper and lower 32-bits and continuing to
312 // |passed| if both evaluate true, or to |failed| if either evaluate false. 328 // |passed| if both evaluate true, or to |failed| if either evaluate false.
313 return CondExpressionHalf(cond, 329 return CondExpressionHalf(cond,
314 UpperHalf, 330 UpperHalf,
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 return ErrorCode(argno, 491 return ErrorCode(argno,
476 width, 492 width,
477 mask, 493 mask,
478 value, 494 value,
479 &*conds_.insert(passed).first, 495 &*conds_.insert(passed).first,
480 &*conds_.insert(failed).first); 496 &*conds_.insert(failed).first);
481 } 497 }
482 498
483 } // namespace bpf_dsl 499 } // namespace bpf_dsl
484 } // namespace sandbox 500 } // namespace sandbox
OLDNEW
« no previous file with comments | « no previous file | sandbox/linux/bpf_dsl/trap_registry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698