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