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

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.cc

Issue 10833044: Refactored ErrorCode into it's own class (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added unittest (and new framework to make this possible) Created 8 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 | Annotate | Revision Log
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 <time.h> 5 #include <time.h>
6 6
7 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 7 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
8 #include "sandbox/linux/seccomp-bpf/verifier.h" 8 #include "sandbox/linux/seccomp-bpf/verifier.h"
9 9
10 // The kernel gives us a sandbox, we turn it into a playground :-) 10 // The kernel gives us a sandbox, we turn it into a playground :-)
11 // This is version 2 of the playground; version 1 was built on top of 11 // This is version 2 of the playground; version 1 was built on top of
12 // pre-BPF seccomp mode. 12 // pre-BPF seccomp mode.
13 namespace playground2 { 13 namespace playground2 {
14 14
15 // We define a really simple sandbox policy. It is just good enough for us 15 // We define a really simple sandbox policy. It is just good enough for us
16 // to tell that the sandbox has actually been activated. 16 // to tell that the sandbox has actually been activated.
17 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) { 17 ErrorCode Sandbox::probeEvaluator(int signo) {
18 switch (signo) { 18 switch (signo) {
19 case __NR_getpid: 19 case __NR_getpid:
20 // Return EPERM so that we can check that the filter actually ran. 20 // Return EPERM so that we can check that the filter actually ran.
21 return EPERM; 21 return ErrorCode(EPERM);
22 case __NR_exit_group: 22 case __NR_exit_group:
23 // Allow exit() with a non-default return code. 23 // Allow exit() with a non-default return code.
24 return SB_ALLOWED; 24 return ErrorCode(ErrorCode::ERR_ALLOWED);
25 default: 25 default:
26 // Make everything else fail in an easily recognizable way. 26 // Make everything else fail in an easily recognizable way.
27 return EINVAL; 27 return ErrorCode(EINVAL);
28 } 28 }
29 } 29 }
30 30
31 void Sandbox::probeProcess(void) { 31 void Sandbox::probeProcess(void) {
32 if (syscall(__NR_getpid) < 0 && errno == EPERM) { 32 if (syscall(__NR_getpid) < 0 && errno == EPERM) {
33 syscall(__NR_exit_group, (intptr_t)100); 33 syscall(__NR_exit_group, (intptr_t)100);
34 } 34 }
35 } 35 }
36 36
37 Sandbox::ErrorCode Sandbox::allowAllEvaluator(int signo) { 37 ErrorCode Sandbox::allowAllEvaluator(int signo) {
38 if (signo < static_cast<int>(MIN_SYSCALL) || 38 if (signo < static_cast<int>(MIN_SYSCALL) ||
39 signo > static_cast<int>(MAX_SYSCALL)) { 39 signo > static_cast<int>(MAX_SYSCALL)) {
40 return ENOSYS; 40 return ErrorCode(ENOSYS);
41 } 41 }
42 return Sandbox::SB_ALLOWED; 42 return ErrorCode(ErrorCode::ERR_ALLOWED);
43 } 43 }
44 44
45 void Sandbox::tryVsyscallProcess(void) { 45 void Sandbox::tryVsyscallProcess(void) {
46 time_t current_time; 46 time_t current_time;
47 // time() is implemented as a vsyscall. With an older glibc, with 47 // time() is implemented as a vsyscall. With an older glibc, with
48 // vsyscall=emulate and some versions of the seccomp BPF patch 48 // vsyscall=emulate and some versions of the seccomp BPF patch
49 // we may get SIGKILL-ed. Detect this! 49 // we may get SIGKILL-ed. Detect this!
50 if (time(&current_time) != static_cast<time_t>(-1)) { 50 if (time(&current_time) != static_cast<time_t>(-1)) {
51 syscall(__NR_exit_group, (intptr_t)100); 51 syscall(__NR_exit_group, (intptr_t)100);
52 } 52 }
53 } 53 }
54 54
55 bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(), 55 bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(),
56 EvaluateSyscall syscallEvaluator, 56 EvaluateSyscall syscallEvaluator,
57 int proc_fd) { 57 int proc_fd) {
58 // Block all signals before forking a child process. This prevents an 58 // Block all signals before forking a child process. This prevents an
59 // attacker from manipulating our test by sending us an unexpected signal. 59 // attacker from manipulating our test by sending us an unexpected signal.
60 sigset_t oldMask, newMask; 60 sigset_t oldMask, newMask;
61 if (sigfillset(&newMask) || 61 if (sigfillset(&newMask) ||
62 sigprocmask(SIG_BLOCK, &newMask, &oldMask)) { 62 sigprocmask(SIG_BLOCK, &newMask, &oldMask)) {
63 die("sigprocmask() failed"); 63 SANDBOX_DIE("sigprocmask() failed");
64 } 64 }
65 int fds[2]; 65 int fds[2];
66 if (pipe2(fds, O_NONBLOCK|O_CLOEXEC)) { 66 if (pipe2(fds, O_NONBLOCK|O_CLOEXEC)) {
67 die("pipe() failed"); 67 SANDBOX_DIE("pipe() failed");
68 } 68 }
69 69
70 pid_t pid = fork(); 70 pid_t pid = fork();
71 if (pid < 0) { 71 if (pid < 0) {
72 // Die if we cannot fork(). We would probably fail a little later 72 // Die if we cannot fork(). We would probably fail a little later
73 // anyway, as the machine is likely very close to running out of 73 // anyway, as the machine is likely very close to running out of
74 // memory. 74 // memory.
75 // But what we don't want to do is return "false", as a crafty 75 // But what we don't want to do is return "false", as a crafty
76 // attacker might cause fork() to fail at will and could trick us 76 // attacker might cause fork() to fail at will and could trick us
77 // into running without a sandbox. 77 // into running without a sandbox.
78 sigprocmask(SIG_SETMASK, &oldMask, NULL); // OK, if it fails 78 sigprocmask(SIG_SETMASK, &oldMask, NULL); // OK, if it fails
79 die("fork() failed unexpectedly"); 79 SANDBOX_DIE("fork() failed unexpectedly");
80 } 80 }
81 81
82 // In the child process 82 // In the child process
83 if (!pid) { 83 if (!pid) {
84 // Test a very simple sandbox policy to verify that we can 84 // Test a very simple sandbox policy to verify that we can
85 // successfully turn on sandboxing. 85 // successfully turn on sandboxing.
86 dryRun_ = true; 86 Die custom_handler(Die::LogToStderr);
87 if (HANDLE_EINTR(close(fds[0])) || 87 if (HANDLE_EINTR(close(fds[0])) ||
88 dup2(fds[1], 2) != 2 || 88 dup2(fds[1], 2) != 2 ||
89 HANDLE_EINTR(close(fds[1]))) { 89 HANDLE_EINTR(close(fds[1]))) {
90 static const char msg[] = "Failed to set up stderr\n"; 90 static const char msg[] = "Failed to set up stderr\n";
91 if (HANDLE_EINTR(write(fds[1], msg, sizeof(msg)-1))) { } 91 if (HANDLE_EINTR(write(fds[1], msg, sizeof(msg)-1))) { }
92 } else { 92 } else {
93 evaluators_.clear(); 93 evaluators_.clear();
94 setSandboxPolicy(syscallEvaluator, NULL); 94 setSandboxPolicy(syscallEvaluator, NULL);
95 setProcFd(proc_fd); 95 setProcFd(proc_fd);
96 startSandbox(); 96 startSandbox();
97 // Run our code in the sandbox 97 // Run our code in the sandbox
98 CodeInSandbox(); 98 CodeInSandbox();
99 } 99 }
100 die(NULL); 100 SANDBOX_DIE(NULL);
101 } 101 }
102 102
103 // In the parent process. 103 // In the parent process.
104 if (HANDLE_EINTR(close(fds[1]))) { 104 if (HANDLE_EINTR(close(fds[1]))) {
105 die("close() failed"); 105 SANDBOX_DIE("close() failed");
106 } 106 }
107 if (sigprocmask(SIG_SETMASK, &oldMask, NULL)) { 107 if (sigprocmask(SIG_SETMASK, &oldMask, NULL)) {
108 die("sigprocmask() failed"); 108 SANDBOX_DIE("sigprocmask() failed");
109 } 109 }
110 int status; 110 int status;
111 if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) { 111 if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) {
112 die("waitpid() failed unexpectedly"); 112 SANDBOX_DIE("waitpid() failed unexpectedly");
113 } 113 }
114 bool rc = WIFEXITED(status) && WEXITSTATUS(status) == 100; 114 bool rc = WIFEXITED(status) && WEXITSTATUS(status) == 100;
115 115
116 // If we fail to support sandboxing, there might be an additional 116 // If we fail to support sandboxing, there might be an additional
117 // error message. If so, this was an entirely unexpected and fatal 117 // error message. If so, this was an entirely unexpected and fatal
118 // failure. We should report the failure and somebody most fix 118 // failure. We should report the failure and somebody most fix
119 // things. This is probably a security-critical bug in the sandboxing 119 // things. This is probably a security-critical bug in the sandboxing
120 // code. 120 // code.
121 if (!rc) { 121 if (!rc) {
122 char buf[4096]; 122 char buf[4096];
123 ssize_t len = HANDLE_EINTR(read(fds[0], buf, sizeof(buf) - 1)); 123 ssize_t len = HANDLE_EINTR(read(fds[0], buf, sizeof(buf) - 1));
124 if (len > 0) { 124 if (len > 0) {
125 while (len > 1 && buf[len-1] == '\n') { 125 while (len > 1 && buf[len-1] == '\n') {
126 --len; 126 --len;
127 } 127 }
128 buf[len] = '\000'; 128 buf[len] = '\000';
129 die(buf); 129 SANDBOX_DIE(buf);
130 } 130 }
131 } 131 }
132 if (HANDLE_EINTR(close(fds[0]))) { 132 if (HANDLE_EINTR(close(fds[0]))) {
133 die("close() failed"); 133 SANDBOX_DIE("close() failed");
134 } 134 }
135 135
136 return rc; 136 return rc;
137 137
138 } 138 }
139 139
140 bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { 140 bool Sandbox::kernelSupportSeccompBPF(int proc_fd) {
141 #if defined(SECCOMP_BPF_VALGRIND_HACKS)
142 if (RUNNING_ON_VALGRIND) {
143 // Valgrind doesn't like our run-time test. Disable testing and assume we
144 // always support sandboxing. This feature should only ever be enabled when
145 // debugging.
146 return true;
147 }
148 #endif
149
141 return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) && 150 return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) &&
142 RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator, 151 RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator,
143 proc_fd); 152 proc_fd);
144 } 153 }
145 154
146 Sandbox::SandboxStatus Sandbox::supportsSeccompSandbox(int proc_fd) { 155 Sandbox::SandboxStatus Sandbox::supportsSeccompSandbox(int proc_fd) {
147 // It the sandbox is currently active, we clearly must have support for 156 // It the sandbox is currently active, we clearly must have support for
148 // sandboxing. 157 // sandboxing.
149 if (status_ == STATUS_ENABLED) { 158 if (status_ == STATUS_ENABLED) {
150 return status_; 159 return status_;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 197 }
189 return status_; 198 return status_;
190 } 199 }
191 200
192 void Sandbox::setProcFd(int proc_fd) { 201 void Sandbox::setProcFd(int proc_fd) {
193 proc_fd_ = proc_fd; 202 proc_fd_ = proc_fd;
194 } 203 }
195 204
196 void Sandbox::startSandbox() { 205 void Sandbox::startSandbox() {
197 if (status_ == STATUS_UNSUPPORTED || status_ == STATUS_UNAVAILABLE) { 206 if (status_ == STATUS_UNSUPPORTED || status_ == STATUS_UNAVAILABLE) {
198 die("Trying to start sandbox, even though it is known to be unavailable"); 207 SANDBOX_DIE("Trying to start sandbox, even though it is known to be "
208 "unavailable");
199 } else if (status_ == STATUS_ENABLED) { 209 } else if (status_ == STATUS_ENABLED) {
200 die("Cannot start sandbox recursively. Use multiple calls to " 210 SANDBOX_DIE("Cannot start sandbox recursively. Use multiple calls to "
201 "setSandboxPolicy() to stack policies instead"); 211 "setSandboxPolicy() to stack policies instead");
202 } 212 }
203 if (proc_fd_ < 0) { 213 if (proc_fd_ < 0) {
204 proc_fd_ = open("/proc", O_RDONLY|O_DIRECTORY); 214 proc_fd_ = open("/proc", O_RDONLY|O_DIRECTORY);
205 } 215 }
206 if (proc_fd_ < 0) { 216 if (proc_fd_ < 0) {
207 // For now, continue in degraded mode, if we can't access /proc. 217 // For now, continue in degraded mode, if we can't access /proc.
208 // In the future, we might want to tighten this requirement. 218 // In the future, we might want to tighten this requirement.
209 } 219 }
210 if (!isSingleThreaded(proc_fd_)) { 220 if (!isSingleThreaded(proc_fd_)) {
211 die("Cannot start sandbox, if process is already multi-threaded"); 221 SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded");
212 } 222 }
213 223
214 // We no longer need access to any files in /proc. We want to do this 224 // We no longer need access to any files in /proc. We want to do this
215 // before installing the filters, just in case that our policy denies 225 // before installing the filters, just in case that our policy denies
216 // close(). 226 // close().
217 if (proc_fd_ >= 0) { 227 if (proc_fd_ >= 0) {
218 if (HANDLE_EINTR(close(proc_fd_))) { 228 if (HANDLE_EINTR(close(proc_fd_))) {
219 die("Failed to close file descriptor for /proc"); 229 SANDBOX_DIE("Failed to close file descriptor for /proc");
220 } 230 }
221 proc_fd_ = -1; 231 proc_fd_ = -1;
222 } 232 }
223 233
224 // Install the filters. 234 // Install the filters.
225 installFilter(); 235 installFilter();
226 236
227 // We are now inside the sandbox. 237 // We are now inside the sandbox.
228 status_ = STATUS_ENABLED; 238 status_ = STATUS_ENABLED;
229 } 239 }
(...skipping 12 matching lines...) Expand all
242 sb.st_nlink != 3 || 252 sb.st_nlink != 3 ||
243 HANDLE_EINTR(close(task))) { 253 HANDLE_EINTR(close(task))) {
244 if (task >= 0) { 254 if (task >= 0) {
245 if (HANDLE_EINTR(close(task))) { } 255 if (HANDLE_EINTR(close(task))) { }
246 } 256 }
247 return false; 257 return false;
248 } 258 }
249 return true; 259 return true;
250 } 260 }
251 261
252 static bool isDenied(const Sandbox::ErrorCode& code) { 262 bool Sandbox::isDenied(const ErrorCode& code) {
253 return (code & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP || 263 return (code.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP ||
254 (code >= (SECCOMP_RET_ERRNO + 1) && 264 (code.err() >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) &&
255 code <= (SECCOMP_RET_ERRNO + 4095)); 265 code.err() <= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MAX_ERRNO));
256 } 266 }
257 267
258 void Sandbox::policySanityChecks(EvaluateSyscall syscallEvaluator, 268 void Sandbox::policySanityChecks(EvaluateSyscall syscallEvaluator,
259 EvaluateArguments) { 269 EvaluateArguments) {
260 // Do some sanity checks on the policy. This will warn users if they do 270 // Do some sanity checks on the policy. This will warn users if they do
261 // things that are likely unsafe and unintended. 271 // things that are likely unsafe and unintended.
262 // We also have similar checks later, when we actually compile the BPF 272 // We also have similar checks later, when we actually compile the BPF
263 // program. That catches problems with incorrectly stacked evaluators. 273 // program. That catches problems with incorrectly stacked evaluators.
264 if (!isDenied(syscallEvaluator(-1))) { 274 if (!isDenied(syscallEvaluator(-1))) {
265 die("Negative system calls should always be disallowed by policy"); 275 SANDBOX_DIE("Negative system calls should always be disallowed by policy");
266 } 276 }
267 #ifndef NDEBUG 277 #ifndef NDEBUG
268 #if defined(__i386__) || defined(__x86_64__) 278 #if defined(__i386__) || defined(__x86_64__)
269 #if defined(__x86_64__) && defined(__ILP32__) 279 #if defined(__x86_64__) && defined(__ILP32__)
270 for (unsigned int sysnum = MIN_SYSCALL & ~0x40000000u; 280 for (unsigned int sysnum = MIN_SYSCALL & ~0x40000000u;
271 sysnum <= (MAX_SYSCALL & ~0x40000000u); 281 sysnum <= (MAX_SYSCALL & ~0x40000000u);
272 ++sysnum) { 282 ++sysnum) {
273 if (!isDenied(syscallEvaluator(sysnum))) { 283 if (!isDenied(syscallEvaluator(sysnum))) {
274 die("In x32 mode, you should not allow any non-x32 system calls"); 284 SANDBOX_DIE("In x32 mode, you should not allow any non-x32 "
285 "system calls");
275 } 286 }
276 } 287 }
277 #else 288 #else
278 for (unsigned int sysnum = MIN_SYSCALL | 0x40000000u; 289 for (unsigned int sysnum = MIN_SYSCALL | 0x40000000u;
279 sysnum <= (MAX_SYSCALL | 0x40000000u); 290 sysnum <= (MAX_SYSCALL | 0x40000000u);
280 ++sysnum) { 291 ++sysnum) {
281 if (!isDenied(syscallEvaluator(sysnum))) { 292 if (!isDenied(syscallEvaluator(sysnum))) {
282 die("x32 system calls should be explicitly disallowed"); 293 SANDBOX_DIE("x32 system calls should be explicitly disallowed");
283 } 294 }
284 } 295 }
285 #endif 296 #endif
286 #endif 297 #endif
287 #endif 298 #endif
288 // Check interesting boundary values just outside of the valid system call 299 // Check interesting boundary values just outside of the valid system call
289 // range: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF, MIN_SYSCALL-1, MAX_SYSCALL+1. 300 // range: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF, MIN_SYSCALL-1, MAX_SYSCALL+1.
290 // They all should be denied. 301 // They all should be denied.
291 if (!isDenied(syscallEvaluator(std::numeric_limits<int>::max())) || 302 if (!isDenied(syscallEvaluator(std::numeric_limits<int>::max())) ||
292 !isDenied(syscallEvaluator(std::numeric_limits<int>::min())) || 303 !isDenied(syscallEvaluator(std::numeric_limits<int>::min())) ||
293 !isDenied(syscallEvaluator(-1)) || 304 !isDenied(syscallEvaluator(-1)) ||
294 !isDenied(syscallEvaluator(static_cast<int>(MIN_SYSCALL) - 1)) || 305 !isDenied(syscallEvaluator(static_cast<int>(MIN_SYSCALL) - 1)) ||
295 !isDenied(syscallEvaluator(static_cast<int>(MAX_SYSCALL) + 1))) { 306 !isDenied(syscallEvaluator(static_cast<int>(MAX_SYSCALL) + 1))) {
296 die("Even for default-allow policies, you must never allow system calls " 307 SANDBOX_DIE("Even for default-allow policies, you must never allow system "
297 "outside of the standard system call range"); 308 "calls outside of the standard system call range");
298 } 309 }
299 return; 310 return;
300 } 311 }
301 312
302 void Sandbox::setSandboxPolicy(EvaluateSyscall syscallEvaluator, 313 void Sandbox::setSandboxPolicy(EvaluateSyscall syscallEvaluator,
303 EvaluateArguments argumentEvaluator) { 314 EvaluateArguments argumentEvaluator) {
304 if (status_ == STATUS_ENABLED) { 315 if (status_ == STATUS_ENABLED) {
305 die("Cannot change policy after sandbox has started"); 316 SANDBOX_DIE("Cannot change policy after sandbox has started");
306 } 317 }
307 policySanityChecks(syscallEvaluator, argumentEvaluator); 318 policySanityChecks(syscallEvaluator, argumentEvaluator);
308 evaluators_.push_back(std::make_pair(syscallEvaluator, argumentEvaluator)); 319 evaluators_.push_back(std::make_pair(syscallEvaluator, argumentEvaluator));
309 } 320 }
310 321
311 void Sandbox::installFilter() { 322 void Sandbox::installFilter() {
312 // Verify that the user pushed a policy. 323 // Verify that the user pushed a policy.
313 if (evaluators_.empty()) { 324 if (evaluators_.empty()) {
314 filter_failed: 325 filter_failed:
315 die("Failed to configure system call filters"); 326 SANDBOX_DIE("Failed to configure system call filters");
316 } 327 }
317 328
318 // Set new SIGSYS handler 329 // Set new SIGSYS handler
319 struct sigaction sa; 330 struct sigaction sa;
320 memset(&sa, 0, sizeof(sa)); 331 memset(&sa, 0, sizeof(sa));
321 sa.sa_sigaction = &sigSys; 332 sa.sa_sigaction = &sigSys;
322 sa.sa_flags = SA_SIGINFO; 333 sa.sa_flags = SA_SIGINFO;
323 if (sigaction(SIGSYS, &sa, NULL) < 0) { 334 if (sigaction(SIGSYS, &sa, NULL) < 0) {
324 goto filter_failed; 335 goto filter_failed;
325 } 336 }
326 337
327 // Unmask SIGSYS 338 // Unmask SIGSYS
328 sigset_t mask; 339 sigset_t mask;
329 if (sigemptyset(&mask) || 340 if (sigemptyset(&mask) ||
330 sigaddset(&mask, SIGSYS) || 341 sigaddset(&mask, SIGSYS) ||
331 sigprocmask(SIG_UNBLOCK, &mask, NULL)) { 342 sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
332 goto filter_failed; 343 goto filter_failed;
333 } 344 }
334 345
335 // We can't handle stacked evaluators, yet. We'll get there eventually 346 // We can't handle stacked evaluators, yet. We'll get there eventually
336 // though. Hang tight. 347 // though. Hang tight.
337 if (evaluators_.size() != 1) { 348 if (evaluators_.size() != 1) {
338 die("Not implemented"); 349 SANDBOX_DIE("Not implemented");
339 } 350 }
340 351
341 // Assemble the BPF filter program. 352 // Assemble the BPF filter program.
342 Program *program = new Program(); 353 Program *program = new Program();
343 if (!program) { 354 if (!program) {
344 die("Out of memory"); 355 SANDBOX_DIE("Out of memory");
345 } 356 }
346 357
347 // If the architecture doesn't match SECCOMP_ARCH, disallow the 358 // If the architecture doesn't match SECCOMP_ARCH, disallow the
348 // system call. 359 // system call.
349 program->push_back((struct sock_filter) 360 program->push_back((struct sock_filter)
350 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch))); 361 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch)));
351 program->push_back((struct sock_filter) 362 program->push_back((struct sock_filter)
352 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0)); 363 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0));
353 364
354 program->push_back((struct sock_filter) 365 program->push_back((struct sock_filter)
355 BPF_STMT(BPF_RET+BPF_K, 366 BPF_STMT(BPF_RET+BPF_K,
356 ErrorCode(bpfFailure, 367 Kill("Invalid audit architecture in BPF filter").err()));
357 "Invalid audit architecture in BPF filter")));
358 368
359 // Grab the system call number, so that we can implement jump tables. 369 // Grab the system call number, so that we can implement jump tables.
360 program->push_back((struct sock_filter) 370 program->push_back((struct sock_filter)
361 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr))); 371 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr)));
362 372
363 // On Intel architectures, verify that system call numbers are in the 373 // On Intel architectures, verify that system call numbers are in the
364 // expected number range. The older i386 and x86-64 APIs clear bit 30 374 // expected number range. The older i386 and x86-64 APIs clear bit 30
365 // on all system calls. The newer x86-32 API always sets bit 30. 375 // on all system calls. The newer x86-32 API always sets bit 30.
366 #if defined(__i386__) || defined(__x86_64__) 376 #if defined(__i386__) || defined(__x86_64__)
367 #if defined(__x86_64__) && defined(__ILP32__) 377 #if defined(__x86_64__) && defined(__ILP32__)
368 program->push_back((struct sock_filter) 378 program->push_back((struct sock_filter)
369 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0)); 379 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0));
370 #else 380 #else
371 program->push_back((struct sock_filter) 381 program->push_back((struct sock_filter)
372 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1)); 382 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1));
373 #endif 383 #endif
374 program->push_back((struct sock_filter) 384 program->push_back((struct sock_filter)
375 BPF_STMT(BPF_RET+BPF_K, 385 BPF_STMT(BPF_RET+BPF_K,
376 ErrorCode(bpfFailure, 386 Kill("Illegal mixing of system call ABIs").err()));
377 "Illegal mixing of system call ABIs")));
378 #endif 387 #endif
379 388
380 389
381 { 390 {
382 // Evaluate all possible system calls and group their ErrorCodes into 391 // Evaluate all possible system calls and group their ErrorCodes into
383 // ranges of identical codes. 392 // ranges of identical codes.
384 Ranges ranges; 393 Ranges ranges;
385 findRanges(&ranges); 394 findRanges(&ranges);
386 395
387 // Compile the system call ranges to an optimized BPF program 396 // Compile the system call ranges to an optimized BPF program
388 RetInsns rets; 397 RetInsns rets;
389 emitJumpStatements(program, &rets, ranges.begin(), ranges.end()); 398 emitJumpStatements(program, &rets, ranges.begin(), ranges.end());
390 emitReturnStatements(program, rets); 399 emitReturnStatements(program, rets);
391 } 400 }
392 401
393 // Make sure compilation resulted in BPF program that executes 402 // Make sure compilation resulted in BPF program that executes
394 // correctly. Otherwise, there is an internal error in our BPF compiler. 403 // correctly. Otherwise, there is an internal error in our BPF compiler.
395 // There is really nothing the caller can do until the bug is fixed. 404 // There is really nothing the caller can do until the bug is fixed.
396 #ifndef NDEBUG 405 #ifndef NDEBUG
397 const char *err = NULL; 406 const char *err = NULL;
398 if (!Verifier::verifyBPF(*program, evaluators_, &err)) { 407 if (!Verifier::verifyBPF(*program, evaluators_, &err)) {
399 die(err); 408 SANDBOX_DIE(err);
400 } 409 }
401 #endif 410 #endif
402 411
403 // We want to be very careful in not imposing any requirements on the 412 // We want to be very careful in not imposing any requirements on the
404 // policies that are set with setSandboxPolicy(). This means, as soon as 413 // policies that are set with setSandboxPolicy(). This means, as soon as
405 // the sandbox is active, we shouldn't be relying on libraries that could 414 // the sandbox is active, we shouldn't be relying on libraries that could
406 // be making system calls. This, for example, means we should avoid 415 // be making system calls. This, for example, means we should avoid
407 // using the heap and we should avoid using STL functions. 416 // using the heap and we should avoid using STL functions.
408 // Temporarily copy the contents of the "program" vector into a 417 // Temporarily copy the contents of the "program" vector into a
409 // stack-allocated array; and then explicitly destroy that object. 418 // stack-allocated array; and then explicitly destroy that object.
410 // This makes sure we don't ex- or implicitly call new/delete after we 419 // This makes sure we don't ex- or implicitly call new/delete after we
411 // installed the BPF filter program in the kernel. Depending on the 420 // installed the BPF filter program in the kernel. Depending on the
412 // system memory allocator that is in effect, these operators can result 421 // system memory allocator that is in effect, these operators can result
413 // in system calls to things like munmap() or brk(). 422 // in system calls to things like munmap() or brk().
414 struct sock_filter bpf[program->size()]; 423 struct sock_filter bpf[program->size()];
415 const struct sock_fprog prog = { 424 const struct sock_fprog prog = {
416 static_cast<unsigned short>(program->size()), bpf }; 425 static_cast<unsigned short>(program->size()), bpf };
417 memcpy(bpf, &(*program)[0], sizeof(bpf)); 426 memcpy(bpf, &(*program)[0], sizeof(bpf));
418 delete program; 427 delete program;
419 428
420 // Release memory that is no longer needed 429 // Release memory that is no longer needed
421 evaluators_.clear(); 430 evaluators_.clear();
431 errMap_.clear();
422 432
423 // Install BPF filter program 433 #if defined(SECCOMP_BPF_VALGRIND_HACKS)
424 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 434 // Valgrind is really not happy about our sandbox. Disable it when running
425 die(dryRun_ ? NULL : "Kernel refuses to enable no-new-privs"); 435 // in Valgrind. This feature is dangerous and should never be enabled by
426 } else { 436 // default. We protect it behind a pre-processor option.
427 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 437 if (!RUNNING_ON_VALGRIND)
428 die(dryRun_ ? NULL : "Kernel refuses to turn on BPF filters"); 438 #endif
439 {
440 // Install BPF filter program
441 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
442 SANDBOX_DIE(Die::HasCustomHandler()
443 ? NULL : "Kernel refuses to enable no-new-privs");
444 } else {
445 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
446 SANDBOX_DIE(Die::HasCustomHandler()
447 ? NULL : "Kernel refuses to turn on BPF filters");
448 }
429 } 449 }
430 } 450 }
431 451
432 return; 452 return;
433 } 453 }
434 454
435 void Sandbox::findRanges(Ranges *ranges) { 455 void Sandbox::findRanges(Ranges *ranges) {
436 // Please note that "struct seccomp_data" defines system calls as a signed 456 // Please note that "struct seccomp_data" defines system calls as a signed
437 // int32_t, but BPF instructions always operate on unsigned quantities. We 457 // int32_t, but BPF instructions always operate on unsigned quantities. We
438 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, 458 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL,
439 // and then verifying that the rest of the number range (both positive and 459 // and then verifying that the rest of the number range (both positive and
440 // negative) all return the same ErrorCode. 460 // negative) all return the same ErrorCode.
441 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first; 461 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first;
442 uint32_t oldSysnum = 0; 462 uint32_t oldSysnum = 0;
443 ErrorCode oldErr = evaluateSyscall(oldSysnum); 463 ErrorCode oldErr = evaluateSyscall(oldSysnum);
444 for (uint32_t sysnum = std::max(1u, MIN_SYSCALL); 464 for (uint32_t sysnum = std::max(1u, MIN_SYSCALL);
445 sysnum <= MAX_SYSCALL + 1; 465 sysnum <= MAX_SYSCALL + 1;
446 ++sysnum) { 466 ++sysnum) {
447 ErrorCode err = evaluateSyscall(static_cast<int>(sysnum)); 467 ErrorCode err = evaluateSyscall(static_cast<int>(sysnum));
448 if (err != oldErr) { 468 if (!err.Equals(oldErr)) {
449 ranges->push_back(Range(oldSysnum, sysnum-1, oldErr)); 469 ranges->push_back(Range(oldSysnum, sysnum-1, oldErr));
450 oldSysnum = sysnum; 470 oldSysnum = sysnum;
451 oldErr = err; 471 oldErr = err;
452 } 472 }
453 } 473 }
454 474
455 // As we looped all the way past the valid system calls (i.e. MAX_SYSCALL+1), 475 // As we looped all the way past the valid system calls (i.e. MAX_SYSCALL+1),
456 // "oldErr" should at this point be the "default" policy for all system call 476 // "oldErr" should at this point be the "default" policy for all system call
457 // numbers that don't have an explicit handler in the system call evaluator. 477 // numbers that don't have an explicit handler in the system call evaluator.
458 // But as we are quite paranoid, we perform some more sanity checks to verify 478 // But as we are quite paranoid, we perform some more sanity checks to verify
459 // that there actually is a consistent "default" policy in the first place. 479 // that there actually is a consistent "default" policy in the first place.
460 // We don't actually iterate over all possible 2^32 values, though. We just 480 // We don't actually iterate over all possible 2^32 values, though. We just
461 // perform spot checks at the boundaries. 481 // perform spot checks at the boundaries.
462 // The cases that we test are: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF. 482 // The cases that we test are: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF.
463 if (oldErr != evaluateSyscall(std::numeric_limits<int>::max()) || 483 if (!oldErr.Equals(evaluateSyscall(std::numeric_limits<int>::max())) ||
464 oldErr != evaluateSyscall(std::numeric_limits<int>::min()) || 484 !oldErr.Equals(evaluateSyscall(std::numeric_limits<int>::min())) ||
465 oldErr != evaluateSyscall(-1)) { 485 !oldErr.Equals(evaluateSyscall(-1))) {
466 die("Invalid seccomp policy"); 486 SANDBOX_DIE("Invalid seccomp policy");
467 } 487 }
468 ranges->push_back( 488 ranges->push_back(
469 Range(oldSysnum, std::numeric_limits<unsigned>::max(), oldErr)); 489 Range(oldSysnum, std::numeric_limits<unsigned>::max(), oldErr));
470 } 490 }
471 491
472 void Sandbox::emitJumpStatements(Program *program, RetInsns *rets, 492 void Sandbox::emitJumpStatements(Program *program, RetInsns *rets,
473 Ranges::const_iterator start, 493 Ranges::const_iterator start,
474 Ranges::const_iterator stop) { 494 Ranges::const_iterator stop) {
475 // We convert the list of system call ranges into jump table that performs 495 // We convert the list of system call ranges into jump table that performs
476 // a binary search over the ranges. 496 // a binary search over the ranges.
477 // As a sanity check, we need to have at least two distinct ranges for us 497 // As a sanity check, we need to have at least two distinct ranges for us
478 // to be able to build a jump table. 498 // to be able to build a jump table.
479 if (stop - start <= 1) { 499 if (stop - start <= 1) {
480 die("Invalid set of system call ranges"); 500 SANDBOX_DIE("Invalid set of system call ranges");
481 } 501 }
482 502
483 // Pick the range object that is located at the mid point of our list. 503 // Pick the range object that is located at the mid point of our list.
484 // We compare our system call number against the lowest valid system call 504 // We compare our system call number against the lowest valid system call
485 // number in this range object. If our number is lower, it is outside of 505 // number in this range object. If our number is lower, it is outside of
486 // this range object. If it is greater or equal, it might be inside. 506 // this range object. If it is greater or equal, it might be inside.
487 Ranges::const_iterator mid = start + (stop - start)/2; 507 Ranges::const_iterator mid = start + (stop - start)/2;
488 Program::size_type jmp = program->size(); 508 Program::size_type jmp = program->size();
489 if (jmp >= SECCOMP_MAX_PROGRAM_SIZE) { 509 if (jmp >= SECCOMP_MAX_PROGRAM_SIZE) {
490 compiler_err: 510 compiler_err:
491 die("Internal compiler error; failed to compile jump table"); 511 SANDBOX_DIE("Internal compiler error; failed to compile jump table");
492 } 512 }
493 program->push_back((struct sock_filter) 513 program->push_back((struct sock_filter)
494 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, mid->from, 514 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, mid->from,
495 // Jump targets are place-holders that will be fixed up later. 515 // Jump targets are place-holders that will be fixed up later.
496 0, 0)); 516 0, 0));
497 517
498 // The comparison turned out to be false; i.e. our system call number is 518 // The comparison turned out to be false; i.e. our system call number is
499 // less than the range object at the mid point of the list. 519 // less than the range object at the mid point of the list.
500 if (mid - start == 1) { 520 if (mid - start == 1) {
501 // If we have narrowed things down to a single range object, we can 521 // If we have narrowed things down to a single range object, we can
502 // return from the BPF filter program. 522 // return from the BPF filter program.
503 // Instead of emitting a BPF_RET statement, we want to coalesce all 523 // Instead of emitting a BPF_RET statement, we want to coalesce all
504 // identical BPF_RET statements into a single instance. This results in 524 // identical BPF_RET statements into a single instance. This results in
505 // a more efficient BPF program that uses less CPU cache. 525 // a more efficient BPF program that uses less CPU cache.
506 // Since all branches in BPF programs have to be forward branches, we 526 // Since all branches in BPF programs have to be forward branches, we
507 // keep track of our current instruction pointer and then fix up the 527 // keep track of our current instruction pointer and then fix up the
508 // branch when we emit the BPF_RET statement in emitReturnStatements(). 528 // branch when we emit the BPF_RET statement in emitReturnStatements().
509 (*rets)[start->err].push_back(FixUp(jmp, false)); 529 (*rets)[start->err.err()].push_back(FixUp(jmp, false));
510 } else { 530 } else {
511 // Sub-divide the list of ranges and continue recursively. 531 // Sub-divide the list of ranges and continue recursively.
512 emitJumpStatements(program, rets, start, mid); 532 emitJumpStatements(program, rets, start, mid);
513 } 533 }
514 534
515 // The comparison turned out to be true; i.e. our system call number is 535 // The comparison turned out to be true; i.e. our system call number is
516 // greater or equal to the range object at the mid point of the list. 536 // greater or equal to the range object at the mid point of the list.
517 if (stop - mid == 1) { 537 if (stop - mid == 1) {
518 // We narrowed things down to a single range object. Remember instruction 538 // We narrowed things down to a single range object. Remember instruction
519 // pointer and exit code, so that we can patch up the target of the jump 539 // pointer and exit code, so that we can patch up the target of the jump
520 // instruction in emitReturnStatements(). 540 // instruction in emitReturnStatements().
521 (*rets)[mid->err].push_back(FixUp(jmp, true)); 541 (*rets)[mid->err.err()].push_back(FixUp(jmp, true));
522 } else { 542 } else {
523 // We now know where the block of instructions for the "true" comparison 543 // We now know where the block of instructions for the "true" comparison
524 // starts. Patch up the jump target of the BPF_JMP instruction that we 544 // starts. Patch up the jump target of the BPF_JMP instruction that we
525 // emitted earlier. 545 // emitted earlier.
526 int distance = program->size() - jmp - 1; 546 int distance = program->size() - jmp - 1;
527 if (distance < 0 || distance > 255) { 547 if (distance < 0 || distance > 255) {
528 goto compiler_err; 548 goto compiler_err;
529 } 549 }
530 (*program)[jmp].jt = distance; 550 (*program)[jmp].jt = distance;
531 551
532 // Sub-divide the list of ranges and continue recursively. 552 // Sub-divide the list of ranges and continue recursively.
533 emitJumpStatements(program, rets, mid, stop); 553 emitJumpStatements(program, rets, mid, stop);
534 } 554 }
535 } 555 }
536 556
537 void Sandbox::emitReturnStatements(Program *program, const RetInsns& rets) { 557 void Sandbox::emitReturnStatements(Program *program, const RetInsns& rets) {
538 // Iterate over the list of distinct exit codes from our BPF filter 558 // Iterate over the list of distinct exit codes from our BPF filter
539 // program and emit the BPF_RET statements. 559 // program and emit the BPF_RET statements.
540 for (RetInsns::const_iterator ret_iter = rets.begin(); 560 for (RetInsns::const_iterator ret_iter = rets.begin();
541 ret_iter != rets.end(); 561 ret_iter != rets.end();
542 ++ret_iter) { 562 ++ret_iter) {
543 Program::size_type ip = program->size(); 563 Program::size_type ip = program->size();
544 if (ip >= SECCOMP_MAX_PROGRAM_SIZE) { 564 if (ip >= SECCOMP_MAX_PROGRAM_SIZE) {
545 die("Internal compiler error; failed to compile jump table"); 565 SANDBOX_DIE("Internal compiler error; failed to compile jump table");
546 } 566 }
547 program->push_back((struct sock_filter) 567 program->push_back((struct sock_filter)
548 BPF_STMT(BPF_RET+BPF_K, ret_iter->first)); 568 BPF_STMT(BPF_RET+BPF_K, ret_iter->first));
549 569
550 // Iterate over the instruction pointers for the BPF_JMP instructions 570 // Iterate over the instruction pointers for the BPF_JMP instructions
551 // that need to be patched up. 571 // that need to be patched up.
552 for (std::vector<FixUp>::const_iterator insn_iter=ret_iter->second.begin(); 572 for (std::vector<FixUp>::const_iterator insn_iter=ret_iter->second.begin();
553 insn_iter != ret_iter->second.end(); 573 insn_iter != ret_iter->second.end();
554 ++insn_iter) { 574 ++insn_iter) {
555 // Jumps are always relative and they are always forward. 575 // Jumps are always relative and they are always forward.
556 int distance = ip - insn_iter->addr - 1; 576 int distance = ip - insn_iter->addr - 1;
557 if (distance < 0 || distance > 255) { 577 if (distance < 0 || distance > 255) {
558 die("Internal compiler error; failed to compile jump table"); 578 SANDBOX_DIE("Internal compiler error; failed to compile jump table");
559 } 579 }
560 580
561 // Decide whether we need to patch up the "true" or the "false" jump 581 // Decide whether we need to patch up the "true" or the "false" jump
562 // target. 582 // target.
563 if (insn_iter->jt) { 583 if (insn_iter->jt) {
564 (*program)[insn_iter->addr].jt = distance; 584 (*program)[insn_iter->addr].jt = distance;
565 } else { 585 } else {
566 (*program)[insn_iter->addr].jf = distance; 586 (*program)[insn_iter->addr].jf = distance;
567 } 587 }
568 } 588 }
569 } 589 }
570 } 590 }
571 591
572 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) { 592 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) {
573 // Various sanity checks to make sure we actually received a signal 593 // Various sanity checks to make sure we actually received a signal
574 // triggered by a BPF filter. If something else triggered SIGSYS 594 // triggered by a BPF filter. If something else triggered SIGSYS
575 // (e.g. kill()), there is really nothing we can do with this signal. 595 // (e.g. kill()), there is really nothing we can do with this signal.
576 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context || 596 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
577 info->si_errno <= 0 || 597 info->si_errno <= 0 ||
578 static_cast<size_t>(info->si_errno) > trapArraySize_) { 598 static_cast<size_t>(info->si_errno) > trapArraySize_) {
579 // die() can call LOG(FATAL). This is not normally async-signal safe 599 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal
580 // and can lead to bugs. We should eventually implement a different 600 // safe and can lead to bugs. We should eventually implement a different
581 // logging and reporting mechanism that is safe to be called from 601 // logging and reporting mechanism that is safe to be called from
582 // the sigSys() handler. 602 // the sigSys() handler.
583 // TODO: If we feel confident that our code otherwise works correctly, we 603 // TODO: If we feel confident that our code otherwise works correctly, we
584 // could actually make an argument that spurious SIGSYS should 604 // could actually make an argument that spurious SIGSYS should
585 // just get silently ignored. TBD 605 // just get silently ignored. TBD
586 sigsys_err: 606 sigsys_err:
587 die("Unexpected SIGSYS received"); 607 SANDBOX_DIE("Unexpected SIGSYS received");
588 } 608 }
589 609
590 // Signal handlers should always preserve "errno". Otherwise, we could 610 // Signal handlers should always preserve "errno". Otherwise, we could
591 // trigger really subtle bugs. 611 // trigger really subtle bugs.
592 int old_errno = errno; 612 int old_errno = errno;
593 613
594 // Obtain the signal context. This, most notably, gives us access to 614 // Obtain the signal context. This, most notably, gives us access to
595 // all CPU registers at the time of the signal. 615 // all CPU registers at the time of the signal.
596 ucontext_t *ctx = reinterpret_cast<ucontext_t *>(void_context); 616 ucontext_t *ctx = reinterpret_cast<ucontext_t *>(void_context);
597 617
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 652
633 // Update the CPU register that stores the return code of the system call 653 // Update the CPU register that stores the return code of the system call
634 // that we just handled, and restore "errno" to the value that it had 654 // that we just handled, and restore "errno" to the value that it had
635 // before entering the signal handler. 655 // before entering the signal handler.
636 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc); 656 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc);
637 errno = old_errno; 657 errno = old_errno;
638 658
639 return; 659 return;
640 } 660 }
641 661
642 intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) { 662 ErrorCode Sandbox::Trap(ErrorCode::TrapFnc fnc, const void *aux) {
643 die(static_cast<char *>(aux));
644 }
645
646 int Sandbox::getTrapId(Sandbox::TrapFnc fnc, const void *aux) {
647 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance 663 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance
648 // of a SECCOMP_RET_TRAP. 664 // of a SECCOMP_RET_TRAP.
649 std::pair<TrapFnc, const void *> key(fnc, aux); 665 std::pair<ErrorCode::TrapFnc, const void *> key(fnc, aux);
650 TrapIds::const_iterator iter = trapIds_.find(key); 666 TrapIds::const_iterator iter = trapIds_.find(key);
667 uint16_t id;
651 if (iter != trapIds_.end()) { 668 if (iter != trapIds_.end()) {
652 // We have seen this pair before. Return the same id that we assigned 669 // We have seen this pair before. Return the same id that we assigned
653 // earlier. 670 // earlier.
654 return iter->second; 671 id = iter->second;
655 } else { 672 } else {
656 // This is a new pair. Remember it and assign a new id. 673 // This is a new pair. Remember it and assign a new id.
657 // Please note that we have to store traps in memory that doesn't get 674 // Please note that we have to store traps in memory that doesn't get
658 // deallocated when the program is shutting down. A memory leak is 675 // deallocated when the program is shutting down. A memory leak is
659 // intentional, because we might otherwise not be able to execute 676 // intentional, because we might otherwise not be able to execute
660 // system calls part way through the program shutting down 677 // system calls part way through the program shutting down
661 if (!traps_) { 678 if (!traps_) {
662 traps_ = new Traps(); 679 traps_ = new Traps();
663 } 680 }
664 Traps::size_type id = traps_->size() + 1; 681 if (traps_->size() >= SECCOMP_RET_DATA) {
665 if (id > SECCOMP_RET_DATA) {
666 // In practice, this is pretty much impossible to trigger, as there 682 // In practice, this is pretty much impossible to trigger, as there
667 // are other kernel limitations that restrict overall BPF program sizes. 683 // are other kernel limitations that restrict overall BPF program sizes.
668 die("Too many SECCOMP_RET_TRAP callback instances"); 684 SANDBOX_DIE("Too many SECCOMP_RET_TRAP callback instances");
669 } 685 }
686 id = traps_->size() + 1;
670 687
671 traps_->push_back(ErrorCode(fnc, aux, id)); 688 traps_->push_back(ErrorCode(fnc, aux, id));
672 trapIds_[key] = id; 689 trapIds_[key] = id;
673 690
674 // We want to access the traps_ vector from our signal handler. But 691 // We want to access the traps_ vector from our signal handler. But
675 // we are not assured that doing so is async-signal safe. On the other 692 // we are not assured that doing so is async-signal safe. On the other
676 // hand, C++ guarantees that the contents of a vector is stored in a 693 // hand, C++ guarantees that the contents of a vector is stored in a
677 // contiguous C-style array. 694 // contiguous C-style array.
678 // So, we look up the address and size of this array outside of the 695 // So, we look up the address and size of this array outside of the
679 // signal handler, where we can safely do so. 696 // signal handler, where we can safely do so.
680 trapArray_ = &(*traps_)[0]; 697 trapArray_ = &(*traps_)[0];
681 trapArraySize_ = id; 698 trapArraySize_ = id;
682 return id;
683 } 699 }
700
701 ErrorCode err = ErrorCode(fnc, aux, id);
702 return errMap_[err.err()] = err;
684 } 703 }
685 704
686 bool Sandbox::dryRun_ = false; 705 intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) {
706 SANDBOX_DIE(static_cast<char *>(aux));
707 }
708
709 ErrorCode Sandbox::Kill(const char *msg) {
710 return Trap(bpfFailure, const_cast<char *>(msg));
711 }
712
687 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 713 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
688 int Sandbox::proc_fd_ = -1; 714 int Sandbox::proc_fd_ = -1;
689 Sandbox::Evaluators Sandbox::evaluators_; 715 Sandbox::Evaluators Sandbox::evaluators_;
716 Sandbox::ErrMap Sandbox::errMap_;
690 Sandbox::Traps *Sandbox::traps_ = NULL; 717 Sandbox::Traps *Sandbox::traps_ = NULL;
691 Sandbox::TrapIds Sandbox::trapIds_; 718 Sandbox::TrapIds Sandbox::trapIds_;
692 Sandbox::ErrorCode *Sandbox::trapArray_ = NULL; 719 ErrorCode *Sandbox::trapArray_ = NULL;
693 size_t Sandbox::trapArraySize_ = 0; 720 size_t Sandbox::trapArraySize_ = 0;
694 721
695 } // namespace 722 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698