Index: sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
index 29c591035972264ed4765f6dde198591c4efb881..79339ffb0c265783706125562dfda6b15b05fe7b 100644 |
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
@@ -20,6 +20,7 @@ |
#include "base/basictypes.h" |
#include "base/logging.h" |
#include "build/build_config.h" |
+#include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h" |
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
@@ -34,6 +35,8 @@ |
#define MAP_STACK 0x20000 // Daisy build environment has old headers. |
#endif |
+using namespace sandbox::bpf_dsl; |
+ |
namespace { |
inline bool IsArchitectureX86_64() { |
@@ -67,20 +70,21 @@ namespace sandbox { |
// Allow Glibc's and Android pthread creation flags, crash on any other |
// thread creation attempts and EPERM attempts to use neither |
// CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations. |
-ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) { |
+ResultExpr RestrictCloneToThreadsAndEPERMFork() { |
+ const Arg<int> flags_arg(0); |
if (!IsAndroid()) { |
const uint64_t kGlibcPthreadFlags = |
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | |
CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | |
CLONE_CHILD_CLEARTID; |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kGlibcPthreadFlags, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- CLONE_VM | CLONE_THREAD, |
- sandbox->Trap(SIGSYSCloneFailure, NULL), |
- ErrorCode(EPERM))); |
+ return If(flags_arg == kGlibcPthreadFlags).Then( |
+ Allow() |
+ ).ElseIf((flags_arg & (CLONE_VM | CLONE_THREAD)) == 0).Then( |
+ Error(EPERM) |
+ ).Else( |
+ bpf_dsl::Trap(SIGSYSCloneFailure, NULL) |
+ ); |
} else { |
const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES | |
CLONE_SIGHAND | CLONE_THREAD | |
@@ -88,40 +92,40 @@ ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) { |
const uint64_t kObsoleteAndroidCloneMask = |
kAndroidCloneMask | CLONE_DETACHED; |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kAndroidCloneMask, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kObsoleteAndroidCloneMask, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- CLONE_VM | CLONE_THREAD, |
- sandbox->Trap(SIGSYSCloneFailure, NULL), |
- ErrorCode(EPERM)))); |
+ return If(flags_arg == kAndroidCloneMask || |
+ flags_arg == kObsoleteAndroidCloneMask).Then( |
+ Allow() |
+ ).ElseIf((flags_arg & (CLONE_VM | CLONE_THREAD)) == 0).Then( |
+ Error(EPERM) |
+ ).Else( |
+ bpf_dsl::Trap(SIGSYSCloneFailure, NULL) |
+ ); |
} |
} |
-ErrorCode RestrictPrctl(SandboxBPF* sandbox) { |
+ResultExpr RestrictPrctl() { |
// Will need to add seccomp compositing in the future. PR_SET_PTRACER is |
// used by breakpad but not needed anymore. |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Trap(SIGSYSPrctlFailure, NULL)))); |
+ const Arg<int> option_arg(0); |
+ return If(option_arg == PR_SET_NAME || |
+ option_arg == PR_SET_DUMPABLE || |
+ option_arg == PR_GET_DUMPABLE).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(SIGSYSPrctlFailure, NULL) |
+ ); |
} |
-ErrorCode RestrictIoctl(SandboxBPF* sandbox) { |
- return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Trap(SIGSYSIoctlFailure, NULL))); |
+ResultExpr RestrictIoctl() { |
+ const Arg<int> request_arg(1); |
+ return If(request_arg == TCGETS || request_arg == FIONREAD).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(SIGSYSIoctlFailure, NULL) |
+ ); |
} |
-ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) { |
+ResultExpr RestrictMmapFlags() { |
// The flags you see are actually the allowed ones, and the variable is a |
// "denied" mask because of the negation operator. |
// Significantly, we don't permit MAP_HUGETLB, or the newer flags such as |
@@ -130,25 +134,29 @@ ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) { |
uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | |
MAP_STACK | MAP_NORESERVE | MAP_FIXED | |
MAP_DENYWRITE); |
- return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- denied_mask, |
- sandbox->Trap(CrashSIGSYS_Handler, NULL), |
- ErrorCode(ErrorCode::ERR_ALLOWED)); |
+ const Arg<int> flags_arg(3); |
+ return If((flags_arg & denied_mask) == 0).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(CrashSIGSYS_Handler, NULL) |
+ ); |
} |
-ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) { |
+ResultExpr RestrictMprotectFlags() { |
// The flags you see are actually the allowed ones, and the variable is a |
// "denied" mask because of the negation operator. |
// Significantly, we don't permit weird undocumented flags such as |
// PROT_GROWSDOWN. |
uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC); |
- return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- denied_mask, |
- sandbox->Trap(CrashSIGSYS_Handler, NULL), |
- ErrorCode(ErrorCode::ERR_ALLOWED)); |
+ const Arg<int> prot_arg(2); |
+ return If((prot_arg & denied_mask) == 0).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(CrashSIGSYS_Handler, NULL) |
+ ); |
} |
-ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) { |
+ResultExpr RestrictFcntlCommands() { |
// We also restrict the flags in F_SETFL. We don't want to permit flags with |
// a history of trouble such as O_DIRECT. The flags you see are actually the |
// allowed ones, and the variable is a "denied" mask because of the negation |
@@ -158,91 +166,64 @@ ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) { |
if (IsArchitectureX86_64() || IsArchitectureI386()) |
kOLargeFileFlag = 0100000; |
- // TODO(jln): add TP_LONG/TP_SIZET types. |
- 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(); |
- |
unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | |
kOLargeFileFlag | O_CLOEXEC | O_NOATIME); |
- return sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_GETFL, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_SETFL, |
- sandbox->Cond(2, mask_long_type, |
- ErrorCode::OP_HAS_ANY_BITS, denied_mask, |
- sandbox->Trap(CrashSIGSYS_Handler, NULL), |
- ErrorCode(ErrorCode::ERR_ALLOWED)), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_GETFD, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_SETFD, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_DUPFD, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_SETLK, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_SETLKW, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_GETLK, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(1, ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Trap(CrashSIGSYS_Handler, NULL)))))))))); |
+ const Arg<int> cmd_arg(1); |
+ const Arg<unsigned long> flags_arg(2); |
+ |
+ return If(cmd_arg == F_GETFL || |
+ (cmd_arg == F_SETFL && (flags_arg & denied_mask) == 0) || |
+ cmd_arg == F_GETFD || |
+ cmd_arg == F_SETFD || |
+ cmd_arg == F_DUPFD || |
+ cmd_arg == F_SETLK || |
+ cmd_arg == F_SETLKW || |
+ cmd_arg == F_GETLK || |
+ cmd_arg == F_DUPFD_CLOEXEC).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(CrashSIGSYS_Handler, NULL) |
+ ); |
} |
#if defined(__i386__) |
-ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) { |
+ResultExpr RestrictSocketcallCommand() { |
// Unfortunately, we are unable to restrict the first parameter to |
// socketpair(2). Whilst initially sounding bad, it's noteworthy that very |
// few protocols actually support socketpair(2). The scary call that we're |
// worried about, socket(2), remains blocked. |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED), |
- ErrorCode(EPERM))))))))); |
+ const Arg<int> call_arg(0); |
+ return If(call_arg == SYS_SOCKETPAIR || |
+ call_arg == SYS_SEND || |
+ call_arg == SYS_RECV || |
+ call_arg == SYS_SENDTO || |
+ call_arg == SYS_RECVFROM || |
+ call_arg == SYS_SHUTDOWN || |
+ call_arg == SYS_SENDMSG || |
+ call_arg == SYS_RECVMSG).Then( |
+ Allow() |
+ ).Else( |
+ Error(EPERM) |
+ ); |
} |
#endif |
-ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) { |
+ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) { |
switch (sysno) { |
case __NR_kill: |
- case __NR_tgkill: |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- target_pid, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Trap(SIGSYSKillFailure, NULL)); |
+ case __NR_tgkill: { |
+ const Arg<pid_t> target_arg(0); |
+ return If(target_arg == target_pid).Then( |
+ Allow() |
+ ).Else( |
+ bpf_dsl::Trap(SIGSYSKillFailure, NULL) |
+ ); |
+ } |
case __NR_tkill: |
- return sandbox->Trap(SIGSYSKillFailure, NULL); |
+ return bpf_dsl::Trap(SIGSYSKillFailure, NULL); |
default: |
NOTREACHED(); |
- return sandbox->Trap(CrashSIGSYS_Handler, NULL); |
+ return bpf_dsl::Trap(CrashSIGSYS_Handler, NULL); |
} |
} |