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/syscall_parameters_restrictions.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <fcntl.h> 10 #include <linux/net.h> 11 #include <sched.h> 12 #include <signal.h> 13 #include <sys/ioctl.h> 14 #include <sys/mman.h> 15 #include <sys/prctl.h> 16 #include <sys/stat.h> 17 #include <sys/types.h> 18 #include <unistd.h> 19 20 #include "base/basictypes.h" 21 #include "base/logging.h" 22 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" 23 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 25 26 #if defined(OS_ANDROID) 27 #if !defined(F_DUPFD_CLOEXEC) 28 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6) 29 #endif 30 #endif 31 32 #if defined(__arm__) && !defined(MAP_STACK) 33 #define MAP_STACK 0x20000 // Daisy build environment has old headers. 34 #endif 35 36 namespace { 37 38 inline bool RunningOnASAN() { 39 #if defined(ADDRESS_SANITIZER) 40 return true; 41 #else 42 return false; 43 #endif 44 } 45 46 inline bool IsArchitectureX86_64() { 47 #if defined(__x86_64__) 48 return true; 49 #else 50 return false; 51 #endif 52 } 53 54 inline bool IsArchitectureI386() { 55 #if defined(__i386__) 56 return true; 57 #else 58 return false; 59 #endif 60 } 61 62 } // namespace. 63 64 namespace sandbox { 65 66 ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) { 67 // Glibc's pthread. 68 if (!RunningOnASAN()) { 69 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 70 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | 71 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | 72 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, 73 ErrorCode(ErrorCode::ERR_ALLOWED), 74 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 75 CLONE_PARENT_SETTID | SIGCHLD, 76 ErrorCode(EPERM), 77 // ARM 78 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 79 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 80 ErrorCode(EPERM), 81 sandbox->Trap(SIGSYSCloneFailure, NULL)))); 82 } else { 83 return ErrorCode(ErrorCode::ERR_ALLOWED); 84 } 85 } 86 87 ErrorCode RestrictPrctl(SandboxBPF* sandbox) { 88 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is 89 // used by breakpad but not needed anymore. 90 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 91 PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED), 92 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 93 PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), 94 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 95 PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), 96 sandbox->Trap(SIGSYSPrctlFailure, NULL)))); 97 } 98 99 ErrorCode RestrictIoctl(SandboxBPF* sandbox) { 100 return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS, 101 ErrorCode(ErrorCode::ERR_ALLOWED), 102 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD, 103 ErrorCode(ErrorCode::ERR_ALLOWED), 104 sandbox->Trap(SIGSYSIoctlFailure, NULL))); 105 } 106 107 ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) { 108 // The flags you see are actually the allowed ones, and the variable is a 109 // "denied" mask because of the negation operator. 110 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as 111 // MAP_POPULATE. 112 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. 113 uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | 114 MAP_STACK | MAP_NORESERVE | MAP_FIXED | 115 MAP_DENYWRITE); 116 return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 117 denied_mask, 118 sandbox->Trap(CrashSIGSYS_Handler, NULL), 119 ErrorCode(ErrorCode::ERR_ALLOWED)); 120 } 121 122 ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) { 123 // The flags you see are actually the allowed ones, and the variable is a 124 // "denied" mask because of the negation operator. 125 // Significantly, we don't permit weird undocumented flags such as 126 // PROT_GROWSDOWN. 127 uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC); 128 return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 129 denied_mask, 130 sandbox->Trap(CrashSIGSYS_Handler, NULL), 131 ErrorCode(ErrorCode::ERR_ALLOWED)); 132 } 133 134 ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) { 135 // We also restrict the flags in F_SETFL. We don't want to permit flags with 136 // a history of trouble such as O_DIRECT. The flags you see are actually the 137 // allowed ones, and the variable is a "denied" mask because of the negation 138 // operator. 139 // Glibc overrides the kernel's O_LARGEFILE value. Account for this. 140 int kOLargeFileFlag = O_LARGEFILE; 141 if (IsArchitectureX86_64() || IsArchitectureI386()) 142 kOLargeFileFlag = 0100000; 143 144 // TODO(jln): add TP_LONG/TP_SIZET types. 145 ErrorCode::ArgType mask_long_type; 146 if (sizeof(long) == 8) 147 mask_long_type = ErrorCode::TP_64BIT; 148 else if (sizeof(long) == 4) 149 mask_long_type = ErrorCode::TP_32BIT; 150 else 151 NOTREACHED(); 152 153 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | 154 kOLargeFileFlag | O_CLOEXEC | O_NOATIME); 155 return sandbox->Cond(1, ErrorCode::TP_32BIT, 156 ErrorCode::OP_EQUAL, F_GETFL, 157 ErrorCode(ErrorCode::ERR_ALLOWED), 158 sandbox->Cond(1, ErrorCode::TP_32BIT, 159 ErrorCode::OP_EQUAL, F_SETFL, 160 sandbox->Cond(2, mask_long_type, 161 ErrorCode::OP_HAS_ANY_BITS, denied_mask, 162 sandbox->Trap(CrashSIGSYS_Handler, NULL), 163 ErrorCode(ErrorCode::ERR_ALLOWED)), 164 sandbox->Cond(1, ErrorCode::TP_32BIT, 165 ErrorCode::OP_EQUAL, F_GETFD, 166 ErrorCode(ErrorCode::ERR_ALLOWED), 167 sandbox->Cond(1, ErrorCode::TP_32BIT, 168 ErrorCode::OP_EQUAL, F_SETFD, 169 ErrorCode(ErrorCode::ERR_ALLOWED), 170 sandbox->Cond(1, ErrorCode::TP_32BIT, 171 ErrorCode::OP_EQUAL, F_DUPFD, 172 ErrorCode(ErrorCode::ERR_ALLOWED), 173 sandbox->Cond(1, ErrorCode::TP_32BIT, 174 ErrorCode::OP_EQUAL, F_SETLK, 175 ErrorCode(ErrorCode::ERR_ALLOWED), 176 sandbox->Cond(1, ErrorCode::TP_32BIT, 177 ErrorCode::OP_EQUAL, F_SETLKW, 178 ErrorCode(ErrorCode::ERR_ALLOWED), 179 sandbox->Cond(1, ErrorCode::TP_32BIT, 180 ErrorCode::OP_EQUAL, F_GETLK, 181 ErrorCode(ErrorCode::ERR_ALLOWED), 182 sandbox->Cond(1, ErrorCode::TP_32BIT, 183 ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC, 184 ErrorCode(ErrorCode::ERR_ALLOWED), 185 sandbox->Trap(CrashSIGSYS_Handler, NULL)))))))))); 186 } 187 188 #if defined(__i386__) 189 ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) { 190 // Unfortunately, we are unable to restrict the first parameter to 191 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very 192 // few protocols actually support socketpair(2). The scary call that we're 193 // worried about, socket(2), remains blocked. 194 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 195 SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), 196 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 197 SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED), 198 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 199 SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED), 200 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 201 SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED), 202 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 203 SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED), 204 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 205 SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED), 206 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 207 SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED), 208 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 209 SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED), 210 ErrorCode(EPERM))))))))); 211 } 212 #endif 213 214 } // namespace sandbox. 215