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