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