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