| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |