baseline_policy.cc revision 010d83a9304c5a91596085d917d248abff47903a
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 26namespace sandbox { 27 28namespace { 29 30bool IsBaselinePolicyAllowed(int sysno) { 31 return SyscallSets::IsAllowedAddressSpaceAccess(sysno) || 32 SyscallSets::IsAllowedBasicScheduler(sysno) || 33 SyscallSets::IsAllowedEpoll(sysno) || 34 SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) || 35 SyscallSets::IsAllowedGeneralIo(sysno) || 36 SyscallSets::IsAllowedGetOrModifySocket(sysno) || 37 SyscallSets::IsAllowedGettime(sysno) || 38 SyscallSets::IsAllowedPrctl(sysno) || 39 SyscallSets::IsAllowedProcessStartOrDeath(sysno) || 40 SyscallSets::IsAllowedSignalHandling(sysno) || 41 SyscallSets::IsFutex(sysno) || 42 SyscallSets::IsGetSimpleId(sysno) || 43 SyscallSets::IsKernelInternalApi(sysno) || 44#if defined(__arm__) 45 SyscallSets::IsArmPrivate(sysno) || 46#endif 47 SyscallSets::IsAllowedOperationOnFd(sysno); 48} 49 50// System calls that will trigger the crashing SIGSYS handler. 51bool IsBaselinePolicyWatched(int sysno) { 52 return SyscallSets::IsAdminOperation(sysno) || 53 SyscallSets::IsAdvancedScheduler(sysno) || 54 SyscallSets::IsAdvancedTimer(sysno) || 55 SyscallSets::IsAsyncIo(sysno) || 56 SyscallSets::IsDebug(sysno) || 57 SyscallSets::IsEventFd(sysno) || 58 SyscallSets::IsExtendedAttributes(sysno) || 59 SyscallSets::IsFaNotify(sysno) || 60 SyscallSets::IsFsControl(sysno) || 61 SyscallSets::IsGlobalFSViewChange(sysno) || 62 SyscallSets::IsGlobalProcessEnvironment(sysno) || 63 SyscallSets::IsGlobalSystemStatus(sysno) || 64 SyscallSets::IsInotify(sysno) || 65 SyscallSets::IsKernelModule(sysno) || 66 SyscallSets::IsKeyManagement(sysno) || 67 SyscallSets::IsKill(sysno) || 68 SyscallSets::IsMessageQueue(sysno) || 69 SyscallSets::IsMisc(sysno) || 70#if defined(__x86_64__) 71 SyscallSets::IsNetworkSocketInformation(sysno) || 72#endif 73 SyscallSets::IsNuma(sysno) || 74 SyscallSets::IsProcessGroupOrSession(sysno) || 75#if defined(__i386__) 76 SyscallSets::IsSocketCall(sysno) || 77#endif 78#if defined(__arm__) 79 SyscallSets::IsArmPciConfig(sysno) || 80#endif 81 SyscallSets::IsTimer(sysno); 82} 83 84// |fs_denied_errno| is the errno return for denied filesystem access. 85ErrorCode EvaluateSyscallImpl(int fs_denied_errno, 86 pid_t current_pid, 87 SandboxBPF* sandbox, 88 int sysno) { 89#if defined(ADDRESS_SANITIZER) 90 if (sysno == __NR_sigaltstack) { 91 // Required for better stack overflow detection in ASan. Disallowed in 92 // non-ASan builds. 93 return ErrorCode(ErrorCode::ERR_ALLOWED); 94 } 95#endif 96 if (IsBaselinePolicyAllowed(sysno)) { 97 return ErrorCode(ErrorCode::ERR_ALLOWED); 98 } 99 100 if (sysno == __NR_clone) { 101 return RestrictCloneToThreadsAndEPERMFork(sandbox); 102 } 103 104#if defined(__x86_64__) || defined(__arm__) 105 if (sysno == __NR_socketpair) { 106 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. 107 COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different); 108 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX, 109 ErrorCode(ErrorCode::ERR_ALLOWED), 110 sandbox->Trap(CrashSIGSYS_Handler, NULL)); 111 } 112#endif 113 114 if (sysno == __NR_madvise) { 115 // Only allow MADV_DONTNEED (aka MADV_FREE). 116 return sandbox->Cond(2, ErrorCode::TP_32BIT, 117 ErrorCode::OP_EQUAL, MADV_DONTNEED, 118 ErrorCode(ErrorCode::ERR_ALLOWED), 119 ErrorCode(EPERM)); 120 } 121 122#if defined(__i386__) || defined(__x86_64__) 123 if (sysno == __NR_mmap) 124 return RestrictMmapFlags(sandbox); 125#endif 126 127#if defined(__i386__) || defined(__arm__) 128 if (sysno == __NR_mmap2) 129 return RestrictMmapFlags(sandbox); 130#endif 131 132 if (sysno == __NR_mprotect) 133 return RestrictMprotectFlags(sandbox); 134 135 if (sysno == __NR_fcntl) 136 return RestrictFcntlCommands(sandbox); 137 138#if defined(__i386__) || defined(__arm__) 139 if (sysno == __NR_fcntl64) 140 return RestrictFcntlCommands(sandbox); 141#endif 142 143 if (SyscallSets::IsKill(sysno)) { 144 return RestrictKillTarget(current_pid, sandbox, sysno); 145 } 146 147 if (SyscallSets::IsFileSystem(sysno) || 148 SyscallSets::IsCurrentDirectory(sysno)) { 149 return ErrorCode(fs_denied_errno); 150 } 151 152 if (SyscallSets::IsAnySystemV(sysno)) { 153 return ErrorCode(EPERM); 154 } 155 156 if (SyscallSets::IsUmask(sysno) || 157 SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) || 158 SyscallSets::IsDeniedGetOrModifySocket(sysno) || 159 SyscallSets::IsProcessPrivilegeChange(sysno)) { 160 return ErrorCode(EPERM); 161 } 162 163#if defined(__i386__) 164 if (SyscallSets::IsSocketCall(sysno)) 165 return RestrictSocketcallCommand(sandbox); 166#endif 167 168 if (IsBaselinePolicyWatched(sysno)) { 169 // Previously unseen syscalls. TODO(jln): some of these should 170 // be denied gracefully right away. 171 return sandbox->Trap(CrashSIGSYS_Handler, NULL); 172 } 173 174 // In any other case crash the program with our SIGSYS handler. 175 return sandbox->Trap(CrashSIGSYS_Handler, NULL); 176} 177 178} // namespace. 179 180// Unfortunately C++03 doesn't allow delegated constructors. 181// Call other constructor when C++11 lands. 182BaselinePolicy::BaselinePolicy() 183 : fs_denied_errno_(EPERM), current_pid_(syscall(__NR_getpid)) {} 184 185BaselinePolicy::BaselinePolicy(int fs_denied_errno) 186 : fs_denied_errno_(fs_denied_errno), current_pid_(syscall(__NR_getpid)) {} 187 188BaselinePolicy::~BaselinePolicy() { 189 // Make sure that this policy is created, used and destroyed by a single 190 // process. 191 DCHECK_EQ(syscall(__NR_getpid), current_pid_); 192} 193 194ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox, 195 int sysno) const { 196 // Make sure that this policy is used in the creating process. 197 if (1 == sysno) { 198 DCHECK_EQ(syscall(__NR_getpid), current_pid_); 199 } 200 return EvaluateSyscallImpl(fs_denied_errno_, current_pid_, sandbox, sysno); 201} 202 203} // namespace sandbox. 204