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