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/baseline_policy.h"
      6 
      7 #include <errno.h>
      8 #include <sys/mman.h>
      9 #include <sys/socket.h>
     10 #include <sys/syscall.h>
     11 #include <sys/types.h>
     12 #include <unistd.h>
     13 
     14 #include "base/logging.h"
     15 #include "build/build_config.h"
     16 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
     17 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
     18 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
     19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
     20 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
     21 #include "sandbox/linux/services/linux_syscalls.h"
     22 
     23 // Changing this implementation will have an effect on *all* policies.
     24 // Currently this means: Renderer/Worker, GPU, Flash and NaCl.
     25 
     26 using sandbox::bpf_dsl::Allow;
     27 using sandbox::bpf_dsl::Arg;
     28 using sandbox::bpf_dsl::Error;
     29 using sandbox::bpf_dsl::If;
     30 using sandbox::bpf_dsl::ResultExpr;
     31 
     32 namespace sandbox {
     33 
     34 namespace {
     35 
     36 bool IsBaselinePolicyAllowed(int sysno) {
     37   return SyscallSets::IsAllowedAddressSpaceAccess(sysno) ||
     38          SyscallSets::IsAllowedBasicScheduler(sysno) ||
     39          SyscallSets::IsAllowedEpoll(sysno) ||
     40          SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) ||
     41          SyscallSets::IsAllowedFutex(sysno) ||
     42          SyscallSets::IsAllowedGeneralIo(sysno) ||
     43          SyscallSets::IsAllowedGetOrModifySocket(sysno) ||
     44          SyscallSets::IsAllowedGettime(sysno) ||
     45          SyscallSets::IsAllowedProcessStartOrDeath(sysno) ||
     46          SyscallSets::IsAllowedSignalHandling(sysno) ||
     47          SyscallSets::IsGetSimpleId(sysno) ||
     48          SyscallSets::IsKernelInternalApi(sysno) ||
     49 #if defined(__arm__)
     50          SyscallSets::IsArmPrivate(sysno) ||
     51 #endif
     52 #if defined(__mips__)
     53          SyscallSets::IsMipsPrivate(sysno) ||
     54 #endif
     55          SyscallSets::IsAllowedOperationOnFd(sysno);
     56 }
     57 
     58 // System calls that will trigger the crashing SIGSYS handler.
     59 bool IsBaselinePolicyWatched(int sysno) {
     60   return SyscallSets::IsAdminOperation(sysno) ||
     61          SyscallSets::IsAdvancedScheduler(sysno) ||
     62          SyscallSets::IsAdvancedTimer(sysno) ||
     63          SyscallSets::IsAsyncIo(sysno) ||
     64          SyscallSets::IsDebug(sysno) ||
     65          SyscallSets::IsEventFd(sysno) ||
     66          SyscallSets::IsExtendedAttributes(sysno) ||
     67          SyscallSets::IsFaNotify(sysno) ||
     68          SyscallSets::IsFsControl(sysno) ||
     69          SyscallSets::IsGlobalFSViewChange(sysno) ||
     70          SyscallSets::IsGlobalProcessEnvironment(sysno) ||
     71          SyscallSets::IsGlobalSystemStatus(sysno) ||
     72          SyscallSets::IsInotify(sysno) ||
     73          SyscallSets::IsKernelModule(sysno) ||
     74          SyscallSets::IsKeyManagement(sysno) ||
     75          SyscallSets::IsKill(sysno) ||
     76          SyscallSets::IsMessageQueue(sysno) ||
     77          SyscallSets::IsMisc(sysno) ||
     78 #if defined(__x86_64__)
     79          SyscallSets::IsNetworkSocketInformation(sysno) ||
     80 #endif
     81          SyscallSets::IsNuma(sysno) ||
     82          SyscallSets::IsPrctl(sysno) ||
     83          SyscallSets::IsProcessGroupOrSession(sysno) ||
     84 #if defined(__i386__) || defined(__mips__)
     85          SyscallSets::IsSocketCall(sysno) ||
     86 #endif
     87 #if defined(__arm__)
     88          SyscallSets::IsArmPciConfig(sysno) ||
     89 #endif
     90 #if defined(__mips__)
     91          SyscallSets::IsMipsMisc(sysno) ||
     92 #endif
     93          SyscallSets::IsTimer(sysno);
     94 }
     95 
     96 // |fs_denied_errno| is the errno return for denied filesystem access.
     97 ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
     98                                pid_t current_pid,
     99                                int sysno) {
    100 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
    101     defined(MEMORY_SANITIZER)
    102   // TCGETS is required by the sanitizers on failure.
    103   if (sysno == __NR_ioctl) {
    104     return RestrictIoctl();
    105   }
    106 
    107   if (sysno == __NR_sched_getaffinity) {
    108     return Allow();
    109   }
    110 
    111   if (sysno == __NR_sigaltstack) {
    112     // Required for better stack overflow detection in ASan. Disallowed in
    113     // non-ASan builds.
    114     return Allow();
    115   }
    116 #endif  // defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||
    117         // defined(MEMORY_SANITIZER)
    118 
    119   if (IsBaselinePolicyAllowed(sysno)) {
    120     return Allow();
    121   }
    122 
    123 #if defined(OS_ANDROID)
    124   // Needed for thread creation.
    125   if (sysno == __NR_sigaltstack)
    126     return Allow();
    127 #endif
    128 
    129   if (sysno == __NR_clock_gettime) {
    130     return RestrictClockID();
    131   }
    132 
    133   if (sysno == __NR_clone) {
    134     return RestrictCloneToThreadsAndEPERMFork();
    135   }
    136 
    137   if (sysno == __NR_fcntl)
    138     return RestrictFcntlCommands();
    139 
    140 #if defined(__i386__) || defined(__arm__) || defined(__mips__)
    141   if (sysno == __NR_fcntl64)
    142     return RestrictFcntlCommands();
    143 #endif
    144 
    145 #if !defined(__aarch64__)
    146   // fork() is never used as a system call (clone() is used instead), but we
    147   // have seen it in fallback code on Android.
    148   if (sysno == __NR_fork) {
    149     return Error(EPERM);
    150   }
    151 #endif
    152 
    153   if (sysno == __NR_futex)
    154     return RestrictFutex();
    155 
    156   if (sysno == __NR_set_robust_list)
    157     return Error(EPERM);
    158 
    159   if (sysno == __NR_getpriority || sysno ==__NR_setpriority)
    160     return RestrictGetSetpriority(current_pid);
    161 
    162   if (sysno == __NR_madvise) {
    163     // Only allow MADV_DONTNEED (aka MADV_FREE).
    164     const Arg<int> advice(2);
    165     return If(advice == MADV_DONTNEED, Allow()).Else(Error(EPERM));
    166   }
    167 
    168 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
    169     defined(__aarch64__)
    170   if (sysno == __NR_mmap)
    171     return RestrictMmapFlags();
    172 #endif
    173 
    174 #if defined(__i386__) || defined(__arm__) || defined(__mips__)
    175   if (sysno == __NR_mmap2)
    176     return RestrictMmapFlags();
    177 #endif
    178 
    179   if (sysno == __NR_mprotect)
    180     return RestrictMprotectFlags();
    181 
    182   if (sysno == __NR_prctl)
    183     return RestrictPrctl();
    184 
    185 #if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
    186     defined(__aarch64__)
    187   if (sysno == __NR_socketpair) {
    188     // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
    189     COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
    190     const Arg<int> domain(0);
    191     return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS());
    192   }
    193 #endif
    194 
    195   if (SyscallSets::IsKill(sysno)) {
    196     return RestrictKillTarget(current_pid, sysno);
    197   }
    198 
    199   if (SyscallSets::IsFileSystem(sysno) ||
    200       SyscallSets::IsCurrentDirectory(sysno)) {
    201     return Error(fs_denied_errno);
    202   }
    203 
    204   if (SyscallSets::IsSeccomp(sysno))
    205     return Error(EPERM);
    206 
    207   if (SyscallSets::IsAnySystemV(sysno)) {
    208     return Error(EPERM);
    209   }
    210 
    211   if (SyscallSets::IsUmask(sysno) ||
    212       SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) ||
    213       SyscallSets::IsDeniedGetOrModifySocket(sysno) ||
    214       SyscallSets::IsProcessPrivilegeChange(sysno)) {
    215     return Error(EPERM);
    216   }
    217 
    218 #if defined(__i386__) || defined(__mips__)
    219   if (SyscallSets::IsSocketCall(sysno))
    220     return RestrictSocketcallCommand();
    221 #endif
    222 
    223   if (IsBaselinePolicyWatched(sysno)) {
    224     // Previously unseen syscalls. TODO(jln): some of these should
    225     // be denied gracefully right away.
    226     return CrashSIGSYS();
    227   }
    228 
    229   // In any other case crash the program with our SIGSYS handler.
    230   return CrashSIGSYS();
    231 }
    232 
    233 }  // namespace.
    234 
    235 // Unfortunately C++03 doesn't allow delegated constructors.
    236 // Call other constructor when C++11 lands.
    237 BaselinePolicy::BaselinePolicy()
    238     : fs_denied_errno_(EPERM), current_pid_(syscall(__NR_getpid)) {}
    239 
    240 BaselinePolicy::BaselinePolicy(int fs_denied_errno)
    241     : fs_denied_errno_(fs_denied_errno), current_pid_(syscall(__NR_getpid)) {}
    242 
    243 BaselinePolicy::~BaselinePolicy() {
    244   // Make sure that this policy is created, used and destroyed by a single
    245   // process.
    246   DCHECK_EQ(syscall(__NR_getpid), current_pid_);
    247 }
    248 
    249 ResultExpr BaselinePolicy::EvaluateSyscall(int sysno) const {
    250   // Sanity check that we're only called with valid syscall numbers.
    251   DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
    252   // Make sure that this policy is used in the creating process.
    253   if (1 == sysno) {
    254     DCHECK_EQ(syscall(__NR_getpid), current_pid_);
    255   }
    256   return EvaluateSyscallImpl(fs_denied_errno_, current_pid_, sysno);
    257 }
    258 
    259 ResultExpr BaselinePolicy::InvalidSyscall() const {
    260   return CrashSIGSYS();
    261 }
    262 
    263 }  // namespace sandbox.
    264