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

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

Issue 10546041: Added a new Verifier class to the BPF compiler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 8 years, 6 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
« no previous file with comments | « sandbox/linux/seccomp-bpf/sandbox_bpf.h ('k') | sandbox/linux/seccomp-bpf/verifier.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/seccomp-bpf/sandbox_bpf.h" 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
6 #include "sandbox/linux/seccomp-bpf/verifier.h"
6 7
7 // The kernel gives us a sandbox, we turn it into a playground :-) 8 // The kernel gives us a sandbox, we turn it into a playground :-)
8 // This is version 2 of the playground; version 1 was built on top of 9 // This is version 2 of the playground; version 1 was built on top of
9 // pre-BPF seccomp mode. 10 // pre-BPF seccomp mode.
10 namespace playground2 { 11 namespace playground2 {
11 12
12 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) { 13 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) {
13 switch (signo) { 14 switch (signo) {
14 case __NR_getpid: 15 case __NR_getpid:
15 // Return EPERM so that we can check that the filter actually ran. 16 // Return EPERM so that we can check that the filter actually ran.
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 290
290 // Evaluate all possible system calls and depending on their 291 // Evaluate all possible system calls and depending on their
291 // exit codes generate a BPF filter. 292 // exit codes generate a BPF filter.
292 // This is very inefficient right now. We need to be much smarter 293 // This is very inefficient right now. We need to be much smarter
293 // eventually. 294 // eventually.
294 // We currently incur a O(N) overhead on each system call, with N 295 // We currently incur a O(N) overhead on each system call, with N
295 // being the number of system calls. It is easy to get this down to 296 // being the number of system calls. It is easy to get this down to
296 // O(log_2(M)) with M being the number of system calls that need special 297 // O(log_2(M)) with M being the number of system calls that need special
297 // treatment. 298 // treatment.
298 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first; 299 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first;
299 for (int sysnum = MIN_SYSCALL; sysnum <= MAX_SYSCALL; ++sysnum) { 300 for (uint32_t sysnum = MIN_SYSCALL; sysnum <= MAX_SYSCALL+1; ++sysnum) {
300 ErrorCode err = evaluateSyscall(sysnum); 301 ErrorCode err = evaluateSyscall(sysnum);
301 int ret; 302 int ret;
302 switch (err) { 303 switch (err) {
303 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6: 304 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6:
304 die("Not implemented"); 305 die("Not implemented");
305 case SB_TRAP: 306 case SB_TRAP:
306 ret = SECCOMP_RET_TRAP; 307 ret = SECCOMP_RET_TRAP;
307 break; 308 break;
308 case SB_ALLOWED: 309 case SB_ALLOWED:
309 ret = SECCOMP_RET_ALLOW; 310 ret = SECCOMP_RET_ALLOW;
310 break; 311 break;
311 default: 312 default:
312 if (err >= static_cast<ErrorCode>(1) && 313 if (err >= static_cast<ErrorCode>(1) &&
313 err <= static_cast<ErrorCode>(4096)) { 314 err <= static_cast<ErrorCode>(4096)) {
314 // We limit errno values to a reasonable range. In fact, the Linux ABI 315 // We limit errno values to a reasonable range. In fact, the Linux ABI
315 // doesn't support errno values outside of this range. 316 // doesn't support errno values outside of this range.
316 ret = SECCOMP_RET_ERRNO + err; 317 ret = SECCOMP_RET_ERRNO + err;
317 } else { 318 } else {
318 die("Invalid ErrorCode reported by sandbox system call evaluator"); 319 die("Invalid ErrorCode reported by sandbox system call evaluator");
319 } 320 }
320 break; 321 break;
321 } 322 }
322 program->push_back((struct sock_filter) 323 if (sysnum <= MAX_SYSCALL) {
323 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1)); 324 // We compute the default behavior (e.g. fail open or fail closed) by
325 // calling the system call evaluator with a system call bigger than
326 // MAX_SYSCALL.
327 // In other words, the very last iteration in our loop becomes the
328 // fallback case and we don't need to do any comparisons.
329 program->push_back((struct sock_filter)
330 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1));
331 }
324 program->push_back((struct sock_filter) 332 program->push_back((struct sock_filter)
325 BPF_STMT(BPF_RET+BPF_K, ret)); 333 BPF_STMT(BPF_RET+BPF_K, ret));
326 } 334 }
327 335
328 // Everything that isn't allowed is forbidden. Eventually, we would 336 // Everything that isn't allowed is forbidden. Eventually, we would
329 // like to have a way to log forbidden calls, when in debug mode. 337 // like to have a way to log forbidden calls, when in debug mode.
330 // TODO: raise a suitable SIGSYS signal 338 // TODO: raise a suitable SIGSYS signal
331 program->push_back((struct sock_filter) 339 program->push_back((struct sock_filter)
332 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 340 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
333 341
342 // Make sure compilation resulted in BPF program that executes
343 // correctly. Otherwise, there is an internal error in our BPF compiler.
344 // There is really nothing the caller can do until the bug is fixed.
345 #ifndef NDEBUG
346 const char *err = NULL;
347 if (!Verifier::verifyBPF(*program, evaluators_, &err)) {
348 die(err);
349 }
350 #endif
351
334 // We want to be very careful in not imposing any requirements on the 352 // We want to be very careful in not imposing any requirements on the
335 // policies that are set with setSandboxPolicy(). This means, as soon as 353 // policies that are set with setSandboxPolicy(). This means, as soon as
336 // the sandbox is active, we shouldn't be relying on libraries that could 354 // the sandbox is active, we shouldn't be relying on libraries that could
337 // be making system calls. This, for example, means we should avoid 355 // be making system calls. This, for example, means we should avoid
338 // using the heap and we should avoid using STL functions. 356 // using the heap and we should avoid using STL functions.
339 // Temporarily copy the contents of the "program" vector into a 357 // Temporarily copy the contents of the "program" vector into a
340 // stack-allocated array; and then explicitly destroy that object. 358 // stack-allocated array; and then explicitly destroy that object.
341 // This makes sure we don't ex- or implicitly call new/delete after we 359 // This makes sure we don't ex- or implicitly call new/delete after we
342 // installed the BPF filter program in the kernel. Depending on the 360 // installed the BPF filter program in the kernel. Depending on the
343 // system memory allocator that is in effect, these operators can result 361 // system memory allocator that is in effect, these operators can result
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 404
387 ctx->uc_mcontext.gregs[REG_RESULT] = reinterpret_cast<greg_t>(rc); 405 ctx->uc_mcontext.gregs[REG_RESULT] = reinterpret_cast<greg_t>(rc);
388 errno = old_errno; 406 errno = old_errno;
389 return; 407 return;
390 } 408 }
391 409
392 410
393 bool Sandbox::dryRun_ = false; 411 bool Sandbox::dryRun_ = false;
394 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 412 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
395 int Sandbox::proc_fd_ = -1; 413 int Sandbox::proc_fd_ = -1;
396 std::vector<std::pair<Sandbox::EvaluateSyscall, 414 Sandbox::Evaluators Sandbox::evaluators_;
397 Sandbox::EvaluateArguments> > Sandbox::evaluators_;
398 415
399 } // namespace 416 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/sandbox_bpf.h ('k') | sandbox/linux/seccomp-bpf/verifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698