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

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

Issue 937303005: Revert of 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"
23 #include "sandbox/linux/system_headers/linux_seccomp.h" 24 #include "sandbox/linux/system_headers/linux_seccomp.h"
24 25
25 namespace sandbox { 26 namespace sandbox {
26 namespace bpf_dsl { 27 namespace bpf_dsl {
27 28
28 namespace { 29 namespace {
29 30
30 #if defined(__i386__) || defined(__x86_64__) 31 #if defined(__i386__) || defined(__x86_64__)
31 const bool kIsIntel = true; 32 const bool kIsIntel = true;
32 #else 33 #else
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 } // namespace 79 } // namespace
79 80
80 struct PolicyCompiler::Range { 81 struct PolicyCompiler::Range {
81 uint32_t from; 82 uint32_t from;
82 CodeGen::Node node; 83 CodeGen::Node node;
83 }; 84 };
84 85
85 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) 86 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry)
86 : policy_(policy), 87 : policy_(policy),
87 registry_(registry), 88 registry_(registry),
88 escapepc_(0),
89 conds_(), 89 conds_(),
90 gen_(), 90 gen_(),
91 has_unsafe_traps_(HasUnsafeTraps(policy_)) { 91 has_unsafe_traps_(HasUnsafeTraps(policy_)) {
92 DCHECK(policy); 92 DCHECK(policy);
93 } 93 }
94 94
95 PolicyCompiler::~PolicyCompiler() { 95 PolicyCompiler::~PolicyCompiler() {
96 } 96 }
97 97
98 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() { 98 scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() {
99 if (!policy_->InvalidSyscall()->IsDeny()) { 99 if (!policy_->InvalidSyscall()->IsDeny()) {
100 SANDBOX_DIE("Policies should deny invalid system calls."); 100 SANDBOX_DIE("Policies should deny invalid system calls.");
101 } 101 }
102 102
103 // If our BPF program has unsafe traps, enable support for them. 103 // If our BPF program has unsafe traps, enable support for them.
104 if (has_unsafe_traps_) { 104 if (has_unsafe_traps_) {
105 // As support for unsafe jumps essentially defeats all the security 105 // As support for unsafe jumps essentially defeats all the security
106 // measures that the sandbox provides, we print a big warning message -- 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 107 // and of course, we make sure to only ever enable this feature if it
108 // is actually requested by the sandbox policy. 108 // is actually requested by the sandbox policy.
109 109 if (Syscall::Call(-1) == -1 && errno == ENOSYS) {
110 CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC"; 110 SANDBOX_DIE(
111 "Support for UnsafeTrap() has not yet been ported to this "
112 "architecture");
113 }
111 114
112 for (int sysnum : kSyscallsRequiredForUnsafeTraps) { 115 for (int sysnum : kSyscallsRequiredForUnsafeTraps) {
113 if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) { 116 if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) {
114 SANDBOX_DIE( 117 SANDBOX_DIE(
115 "Policies that use UnsafeTrap() must unconditionally allow all " 118 "Policies that use UnsafeTrap() must unconditionally allow all "
116 "required system calls"); 119 "required system calls");
117 } 120 }
118 } 121 }
119 122
120 if (!registry_->EnableUnsafeTraps()) { 123 if (!registry_->EnableUnsafeTraps()) {
121 // We should never be able to get here, as UnsafeTrap() should never 124 // We should never be able to get here, as UnsafeTrap() should never
122 // actually return a valid ErrorCode object unless the user set the 125 // actually return a valid ErrorCode object unless the user set the
123 // CHROME_SANDBOX_DEBUGGING environment variable; and therefore, 126 // CHROME_SANDBOX_DEBUGGING environment variable; and therefore,
124 // "has_unsafe_traps" would always be false. But better double-check 127 // "has_unsafe_traps" would always be false. But better double-check
125 // than enabling dangerous code. 128 // than enabling dangerous code.
126 SANDBOX_DIE("We'd rather die than enable unsafe traps"); 129 SANDBOX_DIE("We'd rather die than enable unsafe traps");
127 } 130 }
128 } 131 }
129 132
130 // Assemble the BPF filter program. 133 // Assemble the BPF filter program.
131 scoped_ptr<CodeGen::Program> program(new CodeGen::Program()); 134 scoped_ptr<CodeGen::Program> program(new CodeGen::Program());
132 gen_.Compile(AssemblePolicy(), program.get()); 135 gen_.Compile(AssemblePolicy(), program.get());
133 return program.Pass(); 136 return program.Pass();
134 } 137 }
135 138
136 void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) {
137 escapepc_ = escapepc;
138 }
139
140 CodeGen::Node PolicyCompiler::AssemblePolicy() { 139 CodeGen::Node PolicyCompiler::AssemblePolicy() {
141 // A compiled policy consists of three logical parts: 140 // A compiled policy consists of three logical parts:
142 // 1. Check that the "arch" field matches the expected architecture. 141 // 1. Check that the "arch" field matches the expected architecture.
143 // 2. If the policy involves unsafe traps, check if the syscall was 142 // 2. If the policy involves unsafe traps, check if the syscall was
144 // invoked by Syscall::Call, and then allow it unconditionally. 143 // invoked by Syscall::Call, and then allow it unconditionally.
145 // 3. Check the system call number and jump to the appropriate compiled 144 // 3. Check the system call number and jump to the appropriate compiled
146 // system call policy number. 145 // system call policy number.
147 return CheckArch(MaybeAddEscapeHatch(DispatchSyscall())); 146 return CheckArch(MaybeAddEscapeHatch(DispatchSyscall()));
148 } 147 }
149 148
150 CodeGen::Node PolicyCompiler::CheckArch(CodeGen::Node passed) { 149 CodeGen::Node PolicyCompiler::CheckArch(CodeGen::Node passed) {
151 // If the architecture doesn't match SECCOMP_ARCH, disallow the 150 // If the architecture doesn't match SECCOMP_ARCH, disallow the
152 // system call. 151 // system call.
153 return gen_.MakeInstruction( 152 return gen_.MakeInstruction(
154 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARCH_IDX, 153 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARCH_IDX,
155 gen_.MakeInstruction( 154 gen_.MakeInstruction(
156 BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed, 155 BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed,
157 CompileResult(Kill("Invalid audit architecture in BPF filter")))); 156 CompileResult(Kill("Invalid audit architecture in BPF filter"))));
158 } 157 }
159 158
160 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) { 159 CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) {
161 // If no unsafe traps, then simply return |rest|. 160 // If no unsafe traps, then simply return |rest|.
162 if (!has_unsafe_traps_) { 161 if (!has_unsafe_traps_) {
163 return rest; 162 return rest;
164 } 163 }
165 164
166 // We already enabled unsafe traps in Compile, but enable them again to give 165 // Allow system calls, if they originate from our magic return address
167 // the trap registry a second chance to complain before we add the backdoor. 166 // (which we can query by calling Syscall::Call(-1)).
168 CHECK(registry_->EnableUnsafeTraps()); 167 uint64_t syscall_entry_point =
169 168 static_cast<uint64_t>(static_cast<uintptr_t>(Syscall::Call(-1)));
170 // Allow system calls, if they originate from our magic return address. 169 uint32_t low = static_cast<uint32_t>(syscall_entry_point);
171 const uint32_t lopc = static_cast<uint32_t>(escapepc_); 170 uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32);
172 const uint32_t hipc = static_cast<uint32_t>(escapepc_ >> 32);
173 171
174 // BPF cannot do native 64-bit comparisons, so we have to compare 172 // BPF cannot do native 64-bit comparisons, so we have to compare
175 // both 32-bit halves of the instruction pointer. If they match what 173 // both 32-bit halves of the instruction pointer. If they match what
176 // we expect, we return ERR_ALLOWED. If either or both don't match, 174 // we expect, we return ERR_ALLOWED. If either or both don't match,
177 // we continue evalutating the rest of the sandbox policy. 175 // we continue evalutating the rest of the sandbox policy.
178 // 176 //
179 // For simplicity, we check the full 64-bit instruction pointer even 177 // For simplicity, we check the full 64-bit instruction pointer even
180 // on 32-bit architectures. 178 // on 32-bit architectures.
181 return gen_.MakeInstruction( 179 return gen_.MakeInstruction(
182 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX, 180 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX,
183 gen_.MakeInstruction( 181 gen_.MakeInstruction(
184 BPF_JMP + BPF_JEQ + BPF_K, lopc, 182 BPF_JMP + BPF_JEQ + BPF_K, low,
185 gen_.MakeInstruction( 183 gen_.MakeInstruction(
186 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX, 184 BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX,
187 gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hipc, 185 gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hi,
188 CompileResult(Allow()), rest)), 186 CompileResult(Allow()), rest)),
189 rest)); 187 rest));
190 } 188 }
191 189
192 CodeGen::Node PolicyCompiler::DispatchSyscall() { 190 CodeGen::Node PolicyCompiler::DispatchSyscall() {
193 // Evaluate all possible system calls and group their ErrorCodes into 191 // Evaluate all possible system calls and group their ErrorCodes into
194 // ranges of identical codes. 192 // ranges of identical codes.
195 Ranges ranges; 193 Ranges ranges;
196 FindRanges(&ranges); 194 FindRanges(&ranges);
197 195
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 return ErrorCode(argno, 489 return ErrorCode(argno,
492 width, 490 width,
493 mask, 491 mask,
494 value, 492 value,
495 &*conds_.insert(passed).first, 493 &*conds_.insert(passed).first,
496 &*conds_.insert(failed).first); 494 &*conds_.insert(failed).first);
497 } 495 }
498 496
499 } // namespace bpf_dsl 497 } // namespace bpf_dsl
500 } // namespace sandbox 498 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/policy_compiler.h ('k') | sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698