| Index: components/nacl/loader/nonsfi/nonsfi_sandbox.cc
|
| diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox.cc b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
|
| index 0e4550c5dee9eec964720529f34cfb67ce2dbc3c..7c3121a0f50c1e7fe5fdc6804ae5247fcfc23f93 100644
|
| --- a/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
|
| +++ b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
|
| @@ -17,10 +17,10 @@
|
| #include "base/logging.h"
|
| #include "build/build_config.h"
|
| #include "content/public/common/sandbox_init.h"
|
| +#include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h"
|
| #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
|
| #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
|
| #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
|
| -#include "sandbox/linux/seccomp-bpf/trap.h"
|
| #include "sandbox/linux/services/linux_syscalls.h"
|
|
|
| #if defined(__arm__) && !defined(MAP_STACK)
|
| @@ -28,22 +28,13 @@
|
| #define MAP_STACK 0x20000
|
| #endif
|
|
|
| -using sandbox::ErrorCode;
|
| -using sandbox::SandboxBPF;
|
| +using namespace sandbox::bpf_dsl;
|
|
|
| namespace nacl {
|
| namespace nonsfi {
|
| namespace {
|
|
|
| -ErrorCode RestrictFcntlCommands(SandboxBPF* sb) {
|
| - ErrorCode::ArgType mask_long_type;
|
| - if (sizeof(long) == 8) {
|
| - mask_long_type = ErrorCode::TP_64BIT;
|
| - } else if (sizeof(long) == 4) {
|
| - mask_long_type = ErrorCode::TP_32BIT;
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| +ResultExpr RestrictFcntlCommands() {
|
| // We allow following cases:
|
| // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this.
|
| // 2. F_GETFL: Used by SetNonBlocking in
|
| @@ -55,98 +46,92 @@ ErrorCode RestrictFcntlCommands(SandboxBPF* sb) {
|
| // the return value of F_GETFL, so we need to allow O_ACCMODE in
|
| // addition to O_NONBLOCK.
|
| const unsigned long denied_mask = ~(O_ACCMODE | O_NONBLOCK);
|
| - return sb->Cond(1, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_EQUAL, F_SETFD,
|
| - sb->Cond(2, mask_long_type,
|
| - ErrorCode::OP_EQUAL, FD_CLOEXEC,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL)),
|
| - sb->Cond(1, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_EQUAL, F_GETFL,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Cond(1, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_EQUAL, F_SETFL,
|
| - sb->Cond(2, mask_long_type,
|
| - ErrorCode::OP_HAS_ANY_BITS, denied_mask,
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
|
| - ErrorCode(ErrorCode::ERR_ALLOWED)),
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL))));
|
| + const Arg<int> cmd_arg(1);
|
| + const Arg<unsigned long> extra_arg(2);
|
| + return If((cmd_arg == F_SETFD && extra_arg == FD_CLOEXEC) ||
|
| + (cmd_arg == F_GETFL) ||
|
| + (cmd_arg == F_SETFL && (extra_arg & denied_mask) == 0)).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::CrashSIGSYS_Handler, NULL)
|
| + );
|
| }
|
|
|
| -ErrorCode RestrictClone(SandboxBPF* sb) {
|
| +ResultExpr RestrictClone() {
|
| // We allow clone only for new thread creation.
|
| - return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
|
| - CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
|
| - CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Trap(sandbox::SIGSYSCloneFailure, NULL));
|
| + const int kAllowableFlags =
|
| + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
|
| + CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
|
| + const Arg<int> flag_arg(0);
|
| + return If(flag_arg == kAllowableFlags).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::SIGSYSCloneFailure, NULL)
|
| + );
|
| }
|
|
|
| -ErrorCode RestrictPrctl(SandboxBPF* sb) {
|
| +ResultExpr RestrictPrctl() {
|
| // base::PlatformThread::SetName() uses PR_SET_NAME so we return
|
| // EPERM for it. Otherwise, we will raise SIGSYS.
|
| - return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - PR_SET_NAME, ErrorCode(EPERM),
|
| - sb->Trap(sandbox::SIGSYSPrctlFailure, NULL));
|
| + const Arg<int> option_arg(0);
|
| + return If(option_arg == PR_SET_NAME).Then(
|
| + Error(EPERM)
|
| + ).Else(
|
| + Trap(sandbox::SIGSYSPrctlFailure, NULL)
|
| + );
|
| }
|
|
|
| #if defined(__i386__)
|
| -ErrorCode RestrictSocketcall(SandboxBPF* sb) {
|
| +ResultExpr RestrictSocketcall() {
|
| // We only allow socketpair, sendmsg, and recvmsg.
|
| - return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - SYS_SOCKETPAIR,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - SYS_SENDMSG,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - SYS_RECVMSG,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
|
| - SYS_SHUTDOWN,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL)))));
|
| + const Arg<int> call_arg(0);
|
| + return If(call_arg == SYS_SOCKETPAIR || call_arg == SYS_SENDMSG ||
|
| + call_arg == SYS_RECVMSG || call_arg == SYS_SHUTDOWMN).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::CrashSIGSYS_Handler, NULL)
|
| + );
|
| }
|
| #endif
|
|
|
| -ErrorCode RestrictMprotect(SandboxBPF* sb) {
|
| +ResultExpr RestrictMprotect() {
|
| // TODO(jln, keescook, drewry): Limit the use of mprotect by adding
|
| // some features to linux kernel.
|
| const uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
|
| - return sb->Cond(2, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_HAS_ANY_BITS,
|
| - denied_mask,
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
|
| - ErrorCode(ErrorCode::ERR_ALLOWED));
|
| + const Arg<int> prot_arg(2);
|
| + return If((prot_arg & denied_mask) == 0).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::CrashSIGSYS_Handler, NULL)
|
| + );
|
| }
|
|
|
| -ErrorCode RestrictMmap(SandboxBPF* sb) {
|
| +ResultExpr RestrictMmap() {
|
| const uint32_t denied_flag_mask = ~(MAP_SHARED | MAP_PRIVATE |
|
| MAP_ANONYMOUS | MAP_STACK | MAP_FIXED);
|
| // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper
|
| // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect,
|
| // so we do not need to allow PROT_EXEC in mmap.
|
| const uint32_t denied_prot_mask = ~(PROT_READ | PROT_WRITE);
|
| - return sb->Cond(3, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_HAS_ANY_BITS,
|
| - denied_flag_mask,
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
|
| - sb->Cond(2, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_HAS_ANY_BITS,
|
| - denied_prot_mask,
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
|
| - ErrorCode(ErrorCode::ERR_ALLOWED)));
|
| + const Arg<int> prot_arg(2), flags_arg(3);
|
| + return If((prot_arg & denied_prot_mask) == 0 &&
|
| + (flags_arg & denied_flag_mask) == 0).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::CrashSIGSYS_Handler, NULL)
|
| + );
|
| }
|
|
|
| #if defined(__x86_64__) || defined(__arm__)
|
| -ErrorCode RestrictSocketpair(SandboxBPF* sb) {
|
| +ResultExpr RestrictSocketpair() {
|
| // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
|
| COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
|
| - return sb->Cond(0, ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_EQUAL, AF_UNIX,
|
| - ErrorCode(ErrorCode::ERR_ALLOWED),
|
| - sb->Trap(sandbox::CrashSIGSYS_Handler, NULL));
|
| + const Arg<int> domain_arg(0);
|
| + return If(domain_arg == AF_UNIX).Then(
|
| + Allow()
|
| + ).Else(
|
| + Trap(sandbox::CrashSIGSYS_Handler, NULL)
|
| + );
|
| }
|
| #endif
|
|
|
| @@ -203,8 +188,7 @@ void RunSandboxSanityChecks() {
|
|
|
| } // namespace
|
|
|
| -ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(SandboxBPF* sb,
|
| - int sysno) const {
|
| +ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
|
| switch (sysno) {
|
| // Allowed syscalls.
|
| #if defined(__i386__) || defined(__arm__)
|
| @@ -250,10 +234,10 @@ ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(SandboxBPF* sb,
|
| #if defined(__arm__)
|
| case __ARM_NR_cacheflush:
|
| #endif
|
| - return ErrorCode(ErrorCode::ERR_ALLOWED);
|
| + return Allow();
|
|
|
| case __NR_clone:
|
| - return RestrictClone(sb);
|
| + return RestrictClone();
|
|
|
| #if defined(__x86_64__)
|
| case __NR_fcntl:
|
| @@ -261,7 +245,7 @@ ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(SandboxBPF* sb,
|
| #if defined(__i386__) || defined(__arm__)
|
| case __NR_fcntl64:
|
| #endif
|
| - return RestrictFcntlCommands(sb);
|
| + return RestrictFcntlCommands();
|
|
|
| #if defined(__x86_64__)
|
| case __NR_mmap:
|
| @@ -269,24 +253,24 @@ ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(SandboxBPF* sb,
|
| #if defined(__i386__) || defined(__arm__)
|
| case __NR_mmap2:
|
| #endif
|
| - return RestrictMmap(sb);
|
| + return RestrictMmap();
|
| case __NR_mprotect:
|
| - return RestrictMprotect(sb);
|
| + return RestrictMprotect();
|
|
|
| case __NR_prctl:
|
| - return RestrictPrctl(sb);
|
| + return RestrictPrctl();
|
|
|
| #if defined(__i386__)
|
| case __NR_socketcall:
|
| - return RestrictSocketcall(sb);
|
| + return RestrictSocketcall();
|
| #endif
|
| #if defined(__x86_64__) || defined(__arm__)
|
| case __NR_recvmsg:
|
| case __NR_sendmsg:
|
| case __NR_shutdown:
|
| - return ErrorCode(ErrorCode::ERR_ALLOWED);
|
| + return Allow();
|
| case __NR_socketpair:
|
| - return RestrictSocketpair(sb);
|
| + return RestrictSocketpair();
|
| #endif
|
|
|
| case __NR_brk:
|
| @@ -296,12 +280,12 @@ ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(SandboxBPF* sb,
|
| // is less than the requested address (i.e., brk(addr) < addr).
|
| // So, glibc thinks brk succeeded if we return -EPERM and we
|
| // need to return zero instead.
|
| - return ErrorCode(0);
|
| + return Error(0);
|
|
|
| default:
|
| if (IsGracefullyDenied(sysno))
|
| - return ErrorCode(EPERM);
|
| - return sb->Trap(sandbox::CrashSIGSYS_Handler, NULL);
|
| + return Error(EPERM);
|
| + return Trap(sandbox::CrashSIGSYS_Handler, NULL);
|
| }
|
| }
|
|
|
|
|