Home | History | Annotate | Download | only in seccomp-bpf-helpers
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
      6 
      7 #include <errno.h>
      8 #include <fcntl.h>
      9 #include <fcntl.h>
     10 #include <linux/net.h>
     11 #include <sched.h>
     12 #include <signal.h>
     13 #include <sys/ioctl.h>
     14 #include <sys/mman.h>
     15 #include <sys/prctl.h>
     16 #include <sys/stat.h>
     17 #include <sys/types.h>
     18 #include <unistd.h>
     19 
     20 #include "base/basictypes.h"
     21 #include "base/logging.h"
     22 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
     23 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
     24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
     25 
     26 #if defined(OS_ANDROID)
     27 #if !defined(F_DUPFD_CLOEXEC)
     28 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
     29 #endif
     30 #endif
     31 
     32 #if defined(__arm__) && !defined(MAP_STACK)
     33 #define MAP_STACK 0x20000  // Daisy build environment has old headers.
     34 #endif
     35 
     36 namespace {
     37 
     38 inline bool RunningOnASAN() {
     39 #if defined(ADDRESS_SANITIZER)
     40   return true;
     41 #else
     42   return false;
     43 #endif
     44 }
     45 
     46 inline bool IsArchitectureX86_64() {
     47 #if defined(__x86_64__)
     48   return true;
     49 #else
     50   return false;
     51 #endif
     52 }
     53 
     54 inline bool IsArchitectureI386() {
     55 #if defined(__i386__)
     56   return true;
     57 #else
     58   return false;
     59 #endif
     60 }
     61 
     62 }  // namespace.
     63 
     64 namespace sandbox {
     65 
     66 ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) {
     67   // Glibc's pthread.
     68   if (!RunningOnASAN()) {
     69     return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     70                          CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
     71                          CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
     72                          CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,
     73                          ErrorCode(ErrorCode::ERR_ALLOWED),
     74            sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     75                          CLONE_PARENT_SETTID | SIGCHLD,
     76                          ErrorCode(EPERM),
     77            // ARM
     78            sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     79                          CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,
     80                          ErrorCode(EPERM),
     81            sandbox->Trap(SIGSYSCloneFailure, NULL))));
     82   } else {
     83     return ErrorCode(ErrorCode::ERR_ALLOWED);
     84   }
     85 }
     86 
     87 ErrorCode RestrictPrctl(SandboxBPF* sandbox) {
     88   // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
     89   // used by breakpad but not needed anymore.
     90   return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     91                        PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED),
     92          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     93                        PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
     94          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
     95                        PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
     96          sandbox->Trap(SIGSYSPrctlFailure, NULL))));
     97 }
     98 
     99 ErrorCode RestrictIoctl(SandboxBPF* sandbox) {
    100   return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS,
    101                        ErrorCode(ErrorCode::ERR_ALLOWED),
    102          sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD,
    103                        ErrorCode(ErrorCode::ERR_ALLOWED),
    104                        sandbox->Trap(SIGSYSIoctlFailure, NULL)));
    105 }
    106 
    107 ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) {
    108   // The flags you see are actually the allowed ones, and the variable is a
    109   // "denied" mask because of the negation operator.
    110   // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
    111   // MAP_POPULATE.
    112   // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
    113   uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
    114                            MAP_STACK | MAP_NORESERVE | MAP_FIXED |
    115                            MAP_DENYWRITE);
    116   return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
    117                        denied_mask,
    118                        sandbox->Trap(CrashSIGSYS_Handler, NULL),
    119                        ErrorCode(ErrorCode::ERR_ALLOWED));
    120 }
    121 
    122 ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) {
    123   // The flags you see are actually the allowed ones, and the variable is a
    124   // "denied" mask because of the negation operator.
    125   // Significantly, we don't permit weird undocumented flags such as
    126   // PROT_GROWSDOWN.
    127   uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
    128   return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
    129                        denied_mask,
    130                        sandbox->Trap(CrashSIGSYS_Handler, NULL),
    131                        ErrorCode(ErrorCode::ERR_ALLOWED));
    132 }
    133 
    134 ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) {
    135   // We also restrict the flags in F_SETFL. We don't want to permit flags with
    136   // a history of trouble such as O_DIRECT. The flags you see are actually the
    137   // allowed ones, and the variable is a "denied" mask because of the negation
    138   // operator.
    139   // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
    140   int kOLargeFileFlag = O_LARGEFILE;
    141   if (IsArchitectureX86_64() || IsArchitectureI386())
    142     kOLargeFileFlag = 0100000;
    143 
    144   // TODO(jln): add TP_LONG/TP_SIZET types.
    145   ErrorCode::ArgType mask_long_type;
    146   if (sizeof(long) == 8)
    147     mask_long_type = ErrorCode::TP_64BIT;
    148   else if (sizeof(long) == 4)
    149     mask_long_type = ErrorCode::TP_32BIT;
    150   else
    151     NOTREACHED();
    152 
    153   unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
    154                                 kOLargeFileFlag | O_CLOEXEC | O_NOATIME);
    155   return sandbox->Cond(1, ErrorCode::TP_32BIT,
    156                        ErrorCode::OP_EQUAL, F_GETFL,
    157                        ErrorCode(ErrorCode::ERR_ALLOWED),
    158          sandbox->Cond(1, ErrorCode::TP_32BIT,
    159                        ErrorCode::OP_EQUAL, F_SETFL,
    160                        sandbox->Cond(2, mask_long_type,
    161                                      ErrorCode::OP_HAS_ANY_BITS, denied_mask,
    162                                      sandbox->Trap(CrashSIGSYS_Handler, NULL),
    163                                      ErrorCode(ErrorCode::ERR_ALLOWED)),
    164          sandbox->Cond(1, ErrorCode::TP_32BIT,
    165                        ErrorCode::OP_EQUAL, F_GETFD,
    166                        ErrorCode(ErrorCode::ERR_ALLOWED),
    167          sandbox->Cond(1, ErrorCode::TP_32BIT,
    168                        ErrorCode::OP_EQUAL, F_SETFD,
    169                        ErrorCode(ErrorCode::ERR_ALLOWED),
    170          sandbox->Cond(1, ErrorCode::TP_32BIT,
    171                        ErrorCode::OP_EQUAL, F_DUPFD,
    172                        ErrorCode(ErrorCode::ERR_ALLOWED),
    173          sandbox->Cond(1, ErrorCode::TP_32BIT,
    174                        ErrorCode::OP_EQUAL, F_SETLK,
    175                        ErrorCode(ErrorCode::ERR_ALLOWED),
    176          sandbox->Cond(1, ErrorCode::TP_32BIT,
    177                        ErrorCode::OP_EQUAL, F_SETLKW,
    178                        ErrorCode(ErrorCode::ERR_ALLOWED),
    179          sandbox->Cond(1, ErrorCode::TP_32BIT,
    180                        ErrorCode::OP_EQUAL, F_GETLK,
    181                        ErrorCode(ErrorCode::ERR_ALLOWED),
    182          sandbox->Cond(1, ErrorCode::TP_32BIT,
    183                        ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC,
    184                        ErrorCode(ErrorCode::ERR_ALLOWED),
    185          sandbox->Trap(CrashSIGSYS_Handler, NULL))))))))));
    186 }
    187 
    188 #if defined(__i386__)
    189 ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) {
    190   // Unfortunately, we are unable to restrict the first parameter to
    191   // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
    192   // few protocols actually support socketpair(2). The scary call that we're
    193   // worried about, socket(2), remains blocked.
    194   return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    195                        SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED),
    196          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    197                        SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED),
    198          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    199                        SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED),
    200          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    201                        SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED),
    202          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    203                        SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED),
    204          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    205                        SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED),
    206          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    207                        SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
    208          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
    209                        SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
    210          ErrorCode(EPERM)))))))));
    211 }
    212 #endif
    213 
    214 }  // namespace sandbox.
    215