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

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

Issue 939943002: bpf_dsl: decouple PolicyCompiler from Syscall (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
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/die.h"
22 #include "sandbox/linux/seccomp-bpf/errorcode.h" 22 #include "sandbox/linux/seccomp-bpf/errorcode.h"
23 #include "sandbox/linux/seccomp-bpf/syscall.h"
24 #include "sandbox/linux/system_headers/linux_seccomp.h" 23 #include "sandbox/linux/system_headers/linux_seccomp.h"
25 24
26 namespace sandbox { 25 namespace sandbox {
27 namespace bpf_dsl { 26 namespace bpf_dsl {
28 27
29 namespace { 28 namespace {
30 29
31 #if defined(__i386__) || defined(__x86_64__) 30 #if defined(__i386__) || defined(__x86_64__)
32 const bool kIsIntel = true; 31 const bool kIsIntel = true;
33 #else 32 #else
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 return policy->InvalidSyscall()->HasUnsafeTraps(); 75 return policy->InvalidSyscall()->HasUnsafeTraps();
77 } 76 }
78 77
79 } // namespace 78 } // namespace
80 79
81 struct PolicyCompiler::Range { 80 struct PolicyCompiler::Range {
82 uint32_t from; 81 uint32_t from;
83 CodeGen::Node node; 82 CodeGen::Node node;
84 }; 83 };
85 84
86 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) 85 PolicyCompiler::PolicyCompiler(const Policy* policy,
86 TrapRegistry* registry,
87 uint64_t escapepc)
87 : policy_(policy), 88 : policy_(policy),
88 registry_(registry), 89 registry_(registry),
90 escapepc_(escapepc),
89 conds_(), 91 conds_(),
90 gen_(), 92 gen_(),
91 has_unsafe_traps_(HasUnsafeTraps(policy_)) { 93 has_unsafe_traps_(HasUnsafeTraps(policy_)) {
92 DCHECK(policy); 94 DCHECK(policy);
93 } 95 }
94 96
95 PolicyCompiler::~PolicyCompiler() { 97 PolicyCompiler::~PolicyCompiler() {
96 } 98 }
97 99
98 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() { 100 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() {
99 if (!policy_->InvalidSyscall()->IsDeny()) { 101 if (!policy_->InvalidSyscall()->IsDeny()) {
100 SANDBOX_DIE("Policies should deny invalid system calls."); 102 SANDBOX_DIE("Policies should deny invalid system calls.");
101 } 103 }
102 104
103 // If our BPF program has unsafe traps, enable support for them. 105 // If our BPF program has unsafe traps, enable support for them.
104 if (has_unsafe_traps_) { 106 if (has_unsafe_traps_) {
105 // As support for unsafe jumps essentially defeats all the security 107 // As support for unsafe jumps essentially defeats all the security
106 // measures that the sandbox provides, we print a big warning message -- 108 // 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 109 // and of course, we make sure to only ever enable this feature if it
108 // is actually requested by the sandbox policy. 110 // is actually requested by the sandbox policy.
109 if (Syscall::Call(-1) == -1 && errno == ENOSYS) { 111
110 SANDBOX_DIE( 112 CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC";
111 "Support for UnsafeTrap() has not yet been ported to this "
112 "architecture");
113 }
114 113
115 for (int sysnum : kSyscallsRequiredForUnsafeTraps) { 114 for (int sysnum : kSyscallsRequiredForUnsafeTraps) {
116 if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) { 115 if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) {
117 SANDBOX_DIE( 116 SANDBOX_DIE(
118 "Policies that use UnsafeTrap() must unconditionally allow all " 117 "Policies that use UnsafeTrap() must unconditionally allow all "
119 "required system calls"); 118 "required system calls");
120 } 119 }
121 } 120 }
122 121
123 if (!registry_->EnableUnsafeTraps()) { 122 if (!registry_->EnableUnsafeTraps()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed, 154 BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed,
156 CompileResult(Kill("Invalid audit architecture in BPF filter")))); 155 CompileResult(Kill("Invalid audit architecture in BPF filter"))));
157 } 156 }
158 157
159 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) { 158 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) {
160 // If no unsafe traps, then simply return |rest|. 159 // If no unsafe traps, then simply return |rest|.
161 if (!has_unsafe_traps_) { 160 if (!has_unsafe_traps_) {
162 return rest; 161 return rest;
163 } 162 }
164 163
165 // Allow system calls, if they originate from our magic return address 164 // Allow system calls, if they originate from our magic return address.
166 // (which we can query by calling Syscall::Call(-1)). 165 const uint32_t lopc = static_cast<uint32_t>(escapepc_);
167 uint64_t syscall_entry_point = 166 const uint32_t hipc = static_cast<uint32_t>(escapepc_ >> 32);
168 static_cast<uint64_t>(static_cast<uintptr_t>(Syscall::Call(-1)));
169 uint32_t low = static_cast<uint32_t>(syscall_entry_point);
170 uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32);
171 167
172 // BPF cannot do native 64-bit comparisons, so we have to compare 168 // BPF cannot do native 64-bit comparisons, so we have to compare
173 // both 32-bit halves of the instruction pointer. If they match what 169 // both 32-bit halves of the instruction pointer. If they match what
174 // we expect, we return ERR_ALLOWED. If either or both don't match, 170 // we expect, we return ERR_ALLOWED. If either or both don't match,
175 // we continue evalutating the rest of the sandbox policy. 171 // we continue evalutating the rest of the sandbox policy.
176 // 172 //
177 // For simplicity, we check the full 64-bit instruction pointer even 173 // For simplicity, we check the full 64-bit instruction pointer even
178 // on 32-bit architectures. 174 // on 32-bit architectures.
179 return gen_.MakeInstruction( 175 return gen_.MakeInstruction(
180 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX, 176 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX,
181 gen_.MakeInstruction( 177 gen_.MakeInstruction(
182 BPF_JMP + BPF_JEQ + BPF_K, low, 178 BPF_JMP + BPF_JEQ + BPF_K, lopc,
183 gen_.MakeInstruction( 179 gen_.MakeInstruction(
184 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX, 180 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX,
185 gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hi, 181 gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hipc,
186 CompileResult(Allow()), rest)), 182 CompileResult(Allow()), rest)),
187 rest)); 183 rest));
188 } 184 }
189 185
190 CodeGen::Node PolicyCompiler::DispatchSyscall() { 186 CodeGen::Node PolicyCompiler::DispatchSyscall() {
191 // Evaluate all possible system calls and group their ErrorCodes into 187 // Evaluate all possible system calls and group their ErrorCodes into
192 // ranges of identical codes. 188 // ranges of identical codes.
193 Ranges ranges; 189 Ranges ranges;
194 FindRanges(&ranges); 190 FindRanges(&ranges);
195 191
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 return ErrorCode(argno, 485 return ErrorCode(argno,
490 width, 486 width,
491 mask, 487 mask,
492 value, 488 value,
493 &*conds_.insert(passed).first, 489 &*conds_.insert(passed).first,
494 &*conds_.insert(failed).first); 490 &*conds_.insert(failed).first);
495 } 491 }
496 492
497 } // namespace bpf_dsl 493 } // namespace bpf_dsl
498 } // namespace sandbox 494 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698