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/types.h>
     10 #include <sys/socket.h>
     11 
     12 #include "base/logging.h"
     13 #include "build/build_config.h"
     14 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
     15 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
     16 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
     17 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
     18 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
     19 #include "sandbox/linux/services/linux_syscalls.h"
     20 
     21 // Changing this implementation will have an effect on *all* policies.
     22 // Currently this means: Renderer/Worker, GPU, Flash and NaCl.
     23 
     24 namespace sandbox {
     25 
     26 namespace {
     27 
     28 bool IsBaselinePolicyAllowed(int sysno) {
     29   return SyscallSets::IsAllowedAddressSpaceAccess(sysno) ||
     30          SyscallSets::IsAllowedBasicScheduler(sysno) ||
     31          SyscallSets::IsAllowedEpoll(sysno) ||
     32          SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) ||
     33          SyscallSets::IsAllowedGeneralIo(sysno) ||
     34          SyscallSets::IsAllowedGetOrModifySocket(sysno) ||
     35          SyscallSets::IsAllowedGettime(sysno) ||
     36          SyscallSets::IsAllowedPrctl(sysno) ||
     37          SyscallSets::IsAllowedProcessStartOrDeath(sysno) ||
     38          SyscallSets::IsAllowedSignalHandling(sysno) ||
     39          SyscallSets::IsFutex(sysno) ||
     40          SyscallSets::IsGetSimpleId(sysno) ||
     41          SyscallSets::IsKernelInternalApi(sysno) ||
     42 #if defined(__arm__)
     43          SyscallSets::IsArmPrivate(sysno) ||
     44 #endif
     45          SyscallSets::IsKill(sysno) ||
     46          SyscallSets::IsAllowedOperationOnFd(sysno);
     47 }
     48 
     49 // System calls that will trigger the crashing SIGSYS handler.
     50 bool IsBaselinePolicyWatched(int sysno) {
     51   return SyscallSets::IsAdminOperation(sysno) ||
     52          SyscallSets::IsAdvancedScheduler(sysno) ||
     53          SyscallSets::IsAdvancedTimer(sysno) ||
     54          SyscallSets::IsAsyncIo(sysno) ||
     55          SyscallSets::IsDebug(sysno) ||
     56          SyscallSets::IsEventFd(sysno) ||
     57          SyscallSets::IsExtendedAttributes(sysno) ||
     58          SyscallSets::IsFaNotify(sysno) ||
     59          SyscallSets::IsFsControl(sysno) ||
     60          SyscallSets::IsGlobalFSViewChange(sysno) ||
     61          SyscallSets::IsGlobalProcessEnvironment(sysno) ||
     62          SyscallSets::IsGlobalSystemStatus(sysno) ||
     63          SyscallSets::IsInotify(sysno) ||
     64          SyscallSets::IsKernelModule(sysno) ||
     65          SyscallSets::IsKeyManagement(sysno) ||
     66          SyscallSets::IsMessageQueue(sysno) ||
     67          SyscallSets::IsMisc(sysno) ||
     68 #if defined(__x86_64__)
     69          SyscallSets::IsNetworkSocketInformation(sysno) ||
     70 #endif
     71          SyscallSets::IsNuma(sysno) ||
     72          SyscallSets::IsProcessGroupOrSession(sysno) ||
     73          SyscallSets::IsProcessPrivilegeChange(sysno) ||
     74 #if defined(__i386__)
     75          SyscallSets::IsSocketCall(sysno) ||
     76 #endif
     77 #if defined(__arm__)
     78          SyscallSets::IsArmPciConfig(sysno) ||
     79 #endif
     80          SyscallSets::IsTimer(sysno);
     81 }
     82 
     83 // |fs_denied_errno| is the errno return for denied filesystem access.
     84 ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox,
     85                               int sysno) {
     86   if (IsBaselinePolicyAllowed(sysno)) {
     87     return ErrorCode(ErrorCode::ERR_ALLOWED);
     88   }
     89 
     90 #if defined(__x86_64__) || defined(__arm__)
     91   if (sysno == __NR_socketpair) {
     92     // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
     93     COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
     94     return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX,
     95                          ErrorCode(ErrorCode::ERR_ALLOWED),
     96                          sandbox->Trap(CrashSIGSYS_Handler, NULL));
     97   }
     98 #endif
     99 
    100   if (sysno == __NR_madvise) {
    101     // Only allow MADV_DONTNEED (aka MADV_FREE).
    102     return sandbox->Cond(2, ErrorCode::TP_32BIT,
    103                          ErrorCode::OP_EQUAL, MADV_DONTNEED,
    104                          ErrorCode(ErrorCode::ERR_ALLOWED),
    105                          ErrorCode(EPERM));
    106   }
    107 
    108 #if defined(__i386__) || defined(__x86_64__)
    109   if (sysno == __NR_mmap)
    110     return RestrictMmapFlags(sandbox);
    111 #endif
    112 
    113 #if defined(__i386__) || defined(__arm__)
    114   if (sysno == __NR_mmap2)
    115     return RestrictMmapFlags(sandbox);
    116 #endif
    117 
    118   if (sysno == __NR_mprotect)
    119     return RestrictMprotectFlags(sandbox);
    120 
    121   if (sysno == __NR_fcntl)
    122     return RestrictFcntlCommands(sandbox);
    123 
    124 #if defined(__i386__) || defined(__arm__)
    125   if (sysno == __NR_fcntl64)
    126     return RestrictFcntlCommands(sandbox);
    127 #endif
    128 
    129   if (SyscallSets::IsFileSystem(sysno) ||
    130       SyscallSets::IsCurrentDirectory(sysno)) {
    131     return ErrorCode(fs_denied_errno);
    132   }
    133 
    134   if (SyscallSets::IsAnySystemV(sysno)) {
    135     return ErrorCode(EPERM);
    136   }
    137 
    138   if (SyscallSets::IsUmask(sysno) ||
    139       SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) ||
    140       SyscallSets::IsDeniedGetOrModifySocket(sysno)) {
    141     return ErrorCode(EPERM);
    142   }
    143 
    144 #if defined(__i386__)
    145   if (SyscallSets::IsSocketCall(sysno))
    146     return RestrictSocketcallCommand(sandbox);
    147 #endif
    148 
    149   if (IsBaselinePolicyWatched(sysno)) {
    150     // Previously unseen syscalls. TODO(jln): some of these should
    151     // be denied gracefully right away.
    152     return sandbox->Trap(CrashSIGSYS_Handler, NULL);
    153   }
    154   // In any other case crash the program with our SIGSYS handler.
    155   return sandbox->Trap(CrashSIGSYS_Handler, NULL);
    156 }
    157 
    158 }  // namespace.
    159 
    160 // Unfortunately C++03 doesn't allow delegated constructors.
    161 // Call other constructor when C++11 lands.
    162 BaselinePolicy::BaselinePolicy()
    163     : fs_denied_errno_(EPERM) {}
    164 
    165 BaselinePolicy::BaselinePolicy(int fs_denied_errno)
    166     : fs_denied_errno_(fs_denied_errno) {}
    167 
    168 BaselinePolicy::~BaselinePolicy() {}
    169 
    170 ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox,
    171                                           int sysno) const {
    172   return EvaluateSyscallImpl(fs_denied_errno_, sandbox, sysno);
    173 }
    174 
    175 }  // namespace sandbox.
    176