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); |
} |
} |