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 31using sandbox::bpf_dsl::Allow; 32using sandbox::bpf_dsl::Arg; 33using sandbox::bpf_dsl::Error; 34using sandbox::bpf_dsl::If; 35using sandbox::bpf_dsl::ResultExpr; 36 37namespace sandbox { 38 39namespace { 40 41bool 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. 64bool 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. 102ResultExpr 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. 258BaselinePolicy::BaselinePolicy() : BaselinePolicy(EPERM) {} 259 260BaselinePolicy::BaselinePolicy(int fs_denied_errno) 261 : fs_denied_errno_(fs_denied_errno), policy_pid_(sys_getpid()) { 262} 263 264BaselinePolicy::~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 270ResultExpr 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 280ResultExpr BaselinePolicy::InvalidSyscall() const { 281 return CrashSIGSYS(); 282} 283 284} // namespace sandbox. 285