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