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

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

Issue 1310773006: Update sandbox/linux from upstream (Closed) Base URL: ssh://ssh.github.com/domokit/mojo.git@master
Patch Set: Update to 3909ebfa69566f7374a6900e63cd4d3c73a35378 Created 5 years, 4 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 | « sandbox/linux/bpf_dsl/policy_compiler.h ('k') | sandbox/linux/bpf_dsl/seccomp_macros.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 <sys/syscall.h> 8 #include <sys/syscall.h>
9 9
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" 14 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
15 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" 15 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
16 #include "sandbox/linux/bpf_dsl/codegen.h" 16 #include "sandbox/linux/bpf_dsl/codegen.h"
17 #include "sandbox/linux/bpf_dsl/dump_bpf.h" 17 #include "sandbox/linux/bpf_dsl/dump_bpf.h"
18 #include "sandbox/linux/bpf_dsl/errorcode.h"
18 #include "sandbox/linux/bpf_dsl/policy.h" 19 #include "sandbox/linux/bpf_dsl/policy.h"
19 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" 20 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
20 #include "sandbox/linux/bpf_dsl/syscall_set.h" 21 #include "sandbox/linux/bpf_dsl/syscall_set.h"
21 #include "sandbox/linux/bpf_dsl/verifier.h" 22 #include "sandbox/linux/bpf_dsl/verifier.h"
22 #include "sandbox/linux/seccomp-bpf/errorcode.h"
23 #include "sandbox/linux/system_headers/linux_filter.h" 23 #include "sandbox/linux/system_headers/linux_filter.h"
24 #include "sandbox/linux/system_headers/linux_seccomp.h" 24 #include "sandbox/linux/system_headers/linux_seccomp.h"
25 #include "sandbox/linux/system_headers/linux_syscalls.h" 25 #include "sandbox/linux/system_headers/linux_syscalls.h"
26 26
27 namespace sandbox { 27 namespace sandbox {
28 namespace bpf_dsl { 28 namespace bpf_dsl {
29 29
30 namespace { 30 namespace {
31 31
32 #if defined(__i386__) || defined(__x86_64__) 32 #if defined(__i386__) || defined(__x86_64__)
(...skipping 16 matching lines...) Expand all
49 #if defined(__NR_sigreturn) 49 #if defined(__NR_sigreturn)
50 __NR_sigreturn, 50 __NR_sigreturn,
51 #endif 51 #endif
52 }; 52 };
53 53
54 bool HasExactlyOneBit(uint64_t x) { 54 bool HasExactlyOneBit(uint64_t x) {
55 // Common trick; e.g., see http://stackoverflow.com/a/108329. 55 // Common trick; e.g., see http://stackoverflow.com/a/108329.
56 return x != 0 && (x & (x - 1)) == 0; 56 return x != 0 && (x & (x - 1)) == 0;
57 } 57 }
58 58
59 ResultExpr DefaultPanic(const char* error) {
60 return Kill();
61 }
62
59 // A Trap() handler that returns an "errno" value. The value is encoded 63 // A Trap() handler that returns an "errno" value. The value is encoded
60 // in the "aux" parameter. 64 // in the "aux" parameter.
61 intptr_t ReturnErrno(const struct arch_seccomp_data&, void* aux) { 65 intptr_t ReturnErrno(const struct arch_seccomp_data&, void* aux) {
62 // TrapFnc functions report error by following the native kernel convention 66 // TrapFnc functions report error by following the native kernel convention
63 // of returning an exit code in the range of -1..-4096. They do not try to 67 // of returning an exit code in the range of -1..-4096. They do not try to
64 // set errno themselves. The glibc wrapper that triggered the SIGSYS will 68 // set errno themselves. The glibc wrapper that triggered the SIGSYS will
65 // ultimately do so for us. 69 // ultimately do so for us.
66 int err = reinterpret_cast<intptr_t>(aux) & SECCOMP_RET_DATA; 70 int err = reinterpret_cast<intptr_t>(aux) & SECCOMP_RET_DATA;
67 return -err; 71 return -err;
68 } 72 }
(...skipping 12 matching lines...) Expand all
81 85
82 struct PolicyCompiler::Range { 86 struct PolicyCompiler::Range {
83 uint32_t from; 87 uint32_t from;
84 CodeGen::Node node; 88 CodeGen::Node node;
85 }; 89 };
86 90
87 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) 91 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry)
88 : policy_(policy), 92 : policy_(policy),
89 registry_(registry), 93 registry_(registry),
90 escapepc_(0), 94 escapepc_(0),
95 panic_func_(DefaultPanic),
91 conds_(), 96 conds_(),
92 gen_(), 97 gen_(),
93 has_unsafe_traps_(HasUnsafeTraps(policy_)) { 98 has_unsafe_traps_(HasUnsafeTraps(policy_)) {
94 DCHECK(policy); 99 DCHECK(policy);
95 } 100 }
96 101
97 PolicyCompiler::~PolicyCompiler() { 102 PolicyCompiler::~PolicyCompiler() {
98 } 103 }
99 104
100 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile(bool verify) { 105 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile(bool verify) {
(...skipping 29 matching lines...) Expand all
130 } 135 }
131 } 136 }
132 137
133 return program.Pass(); 138 return program.Pass();
134 } 139 }
135 140
136 void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) { 141 void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) {
137 escapepc_ = escapepc; 142 escapepc_ = escapepc;
138 } 143 }
139 144
145 void PolicyCompiler::SetPanicFunc(PanicFunc panic_func) {
146 panic_func_ = panic_func;
147 }
148
140 CodeGen::Node PolicyCompiler::AssemblePolicy() { 149 CodeGen::Node PolicyCompiler::AssemblePolicy() {
141 // A compiled policy consists of three logical parts: 150 // A compiled policy consists of three logical parts:
142 // 1. Check that the "arch" field matches the expected architecture. 151 // 1. Check that the "arch" field matches the expected architecture.
143 // 2. If the policy involves unsafe traps, check if the syscall was 152 // 2. If the policy involves unsafe traps, check if the syscall was
144 // invoked by Syscall::Call, and then allow it unconditionally. 153 // invoked by Syscall::Call, and then allow it unconditionally.
145 // 3. Check the system call number and jump to the appropriate compiled 154 // 3. Check the system call number and jump to the appropriate compiled
146 // system call policy number. 155 // system call policy number.
147 return CheckArch(MaybeAddEscapeHatch(DispatchSyscall())); 156 return CheckArch(MaybeAddEscapeHatch(DispatchSyscall()));
148 } 157 }
149 158
150 CodeGen::Node PolicyCompiler::CheckArch(CodeGen::Node passed) { 159 CodeGen::Node PolicyCompiler::CheckArch(CodeGen::Node passed) {
151 // If the architecture doesn't match SECCOMP_ARCH, disallow the 160 // If the architecture doesn't match SECCOMP_ARCH, disallow the
152 // system call. 161 // system call.
153 return gen_.MakeInstruction( 162 return gen_.MakeInstruction(
154 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARCH_IDX, 163 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARCH_IDX,
155 gen_.MakeInstruction( 164 gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed,
156 BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed, 165 CompileResult(panic_func_(
157 CompileResult(Kill("Invalid audit architecture in BPF filter")))); 166 "Invalid audit architecture in BPF filter"))));
158 } 167 }
159 168
160 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) { 169 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) {
161 // If no unsafe traps, then simply return |rest|. 170 // If no unsafe traps, then simply return |rest|.
162 if (!has_unsafe_traps_) { 171 if (!has_unsafe_traps_) {
163 return rest; 172 return rest;
164 } 173 }
165 174
166 // We already enabled unsafe traps in Compile, but enable them again to give 175 // We already enabled unsafe traps in Compile, but enable them again to give
167 // the trap registry a second chance to complain before we add the backdoor. 176 // the trap registry a second chance to complain before we add the backdoor.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 // execute the jump table. 211 // execute the jump table.
203 return gen_.MakeInstruction( 212 return gen_.MakeInstruction(
204 BPF_LD + BPF_W + BPF_ABS, SECCOMP_NR_IDX, CheckSyscallNumber(jumptable)); 213 BPF_LD + BPF_W + BPF_ABS, SECCOMP_NR_IDX, CheckSyscallNumber(jumptable));
205 } 214 }
206 215
207 CodeGen::Node PolicyCompiler::CheckSyscallNumber(CodeGen::Node passed) { 216 CodeGen::Node PolicyCompiler::CheckSyscallNumber(CodeGen::Node passed) {
208 if (kIsIntel) { 217 if (kIsIntel) {
209 // On Intel architectures, verify that system call numbers are in the 218 // On Intel architectures, verify that system call numbers are in the
210 // expected number range. 219 // expected number range.
211 CodeGen::Node invalidX32 = 220 CodeGen::Node invalidX32 =
212 CompileResult(Kill("Illegal mixing of system call ABIs")); 221 CompileResult(panic_func_("Illegal mixing of system call ABIs"));
213 if (kIsX32) { 222 if (kIsX32) {
214 // The newer x32 API always sets bit 30. 223 // The newer x32 API always sets bit 30.
215 return gen_.MakeInstruction( 224 return gen_.MakeInstruction(
216 BPF_JMP + BPF_JSET + BPF_K, 0x40000000, passed, invalidX32); 225 BPF_JMP + BPF_JSET + BPF_K, 0x40000000, passed, invalidX32);
217 } else { 226 } else {
218 // The older i386 and x86-64 APIs clear bit 30 on all system calls. 227 // The older i386 and x86-64 APIs clear bit 30 on all system calls.
219 return gen_.MakeInstruction( 228 return gen_.MakeInstruction(
220 BPF_JMP + BPF_JSET + BPF_K, 0x40000000, invalidX32, passed); 229 BPF_JMP + BPF_JSET + BPF_K, 0x40000000, invalidX32, passed);
221 } 230 }
222 } 231 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 BPF_LD + BPF_W + BPF_ABS, 447 BPF_LD + BPF_W + BPF_ABS,
439 idx, 448 idx,
440 gen_.MakeInstruction( 449 gen_.MakeInstruction(
441 BPF_ALU + BPF_AND + BPF_K, 450 BPF_ALU + BPF_AND + BPF_K,
442 mask, 451 mask,
443 gen_.MakeInstruction( 452 gen_.MakeInstruction(
444 BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); 453 BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed)));
445 } 454 }
446 455
447 ErrorCode PolicyCompiler::Unexpected64bitArgument() { 456 ErrorCode PolicyCompiler::Unexpected64bitArgument() {
448 return Kill("Unexpected 64bit argument detected")->Compile(this); 457 return panic_func_("Unexpected 64bit argument detected")->Compile(this);
449 } 458 }
450 459
451 ErrorCode PolicyCompiler::Error(int err) { 460 ErrorCode PolicyCompiler::Error(int err) {
452 if (has_unsafe_traps_) { 461 if (has_unsafe_traps_) {
453 // When inside an UnsafeTrap() callback, we want to allow all system calls. 462 // When inside an UnsafeTrap() callback, we want to allow all system calls.
454 // This means, we must conditionally disable the sandbox -- and that's not 463 // This means, we must conditionally disable the sandbox -- and that's not
455 // something that kernel-side BPF filters can do, as they cannot inspect 464 // something that kernel-side BPF filters can do, as they cannot inspect
456 // any state other than the syscall arguments. 465 // any state other than the syscall arguments.
457 // But if we redirect all error handlers to user-space, then we can easily 466 // But if we redirect all error handlers to user-space, then we can easily
458 // make this decision. 467 // make this decision.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 return ErrorCode(argno, 499 return ErrorCode(argno,
491 width, 500 width,
492 mask, 501 mask,
493 value, 502 value,
494 &*conds_.insert(passed).first, 503 &*conds_.insert(passed).first,
495 &*conds_.insert(failed).first); 504 &*conds_.insert(failed).first);
496 } 505 }
497 506
498 } // namespace bpf_dsl 507 } // namespace bpf_dsl
499 } // namespace sandbox 508 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/policy_compiler.h ('k') | sandbox/linux/bpf_dsl/seccomp_macros.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698