| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" | 5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <linux/futex.h> | 10 #include <linux/futex.h> |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 inline bool IsArchitectureMips() { | 72 inline bool IsArchitectureMips() { |
| 73 #if defined(__mips__) | 73 #if defined(__mips__) |
| 74 return true; | 74 return true; |
| 75 #else | 75 #else |
| 76 return false; | 76 return false; |
| 77 #endif | 77 #endif |
| 78 } | 78 } |
| 79 | 79 |
| 80 } // namespace. | 80 } // namespace. |
| 81 | 81 |
| 82 #define CASES SANDBOX_BPF_DSL_CASES |
| 83 |
| 82 using sandbox::bpf_dsl::Allow; | 84 using sandbox::bpf_dsl::Allow; |
| 83 using sandbox::bpf_dsl::Arg; | 85 using sandbox::bpf_dsl::Arg; |
| 84 using sandbox::bpf_dsl::BoolExpr; | 86 using sandbox::bpf_dsl::BoolExpr; |
| 85 using sandbox::bpf_dsl::Error; | 87 using sandbox::bpf_dsl::Error; |
| 86 using sandbox::bpf_dsl::If; | 88 using sandbox::bpf_dsl::If; |
| 87 using sandbox::bpf_dsl::ResultExpr; | 89 using sandbox::bpf_dsl::ResultExpr; |
| 88 | 90 |
| 89 // TODO(mdempsky): Make BoolExpr a standalone class so these operators can | 91 // TODO(mdempsky): Make BoolExpr a standalone class so these operators can |
| 90 // be resolved via argument-dependent lookup. | 92 // be resolved via argument-dependent lookup. |
| 91 using sandbox::bpf_dsl::operator||; | 93 using sandbox::bpf_dsl::operator||; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 116 | 118 |
| 117 return If(IsAndroid() ? android_test : glibc_test, Allow()) | 119 return If(IsAndroid() ? android_test : glibc_test, Allow()) |
| 118 .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM)) | 120 .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM)) |
| 119 .Else(CrashSIGSYSClone()); | 121 .Else(CrashSIGSYSClone()); |
| 120 } | 122 } |
| 121 | 123 |
| 122 ResultExpr RestrictPrctl() { | 124 ResultExpr RestrictPrctl() { |
| 123 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is | 125 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is |
| 124 // used by breakpad but not needed anymore. | 126 // used by breakpad but not needed anymore. |
| 125 const Arg<int> option(0); | 127 const Arg<int> option(0); |
| 126 return If(option == PR_GET_NAME || option == PR_SET_NAME || | 128 return Switch(option) |
| 127 option == PR_GET_DUMPABLE || option == PR_SET_DUMPABLE, | 129 .CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE), |
| 128 Allow()).Else(CrashSIGSYSPrctl()); | 130 Allow()) |
| 131 .Default(CrashSIGSYSPrctl()); |
| 129 } | 132 } |
| 130 | 133 |
| 131 ResultExpr RestrictIoctl() { | 134 ResultExpr RestrictIoctl() { |
| 132 const Arg<int> request(1); | 135 const Arg<int> request(1); |
| 133 return If(request == TCGETS || request == FIONREAD, Allow()) | 136 return Switch(request).CASES((TCGETS, FIONREAD), Allow()).Default( |
| 134 .Else(CrashSIGSYSIoctl()); | 137 CrashSIGSYSIoctl()); |
| 135 } | 138 } |
| 136 | 139 |
| 137 ResultExpr RestrictMmapFlags() { | 140 ResultExpr RestrictMmapFlags() { |
| 138 // The flags you see are actually the allowed ones, and the variable is a | 141 // The flags you see are actually the allowed ones, and the variable is a |
| 139 // "denied" mask because of the negation operator. | 142 // "denied" mask because of the negation operator. |
| 140 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as | 143 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as |
| 141 // MAP_POPULATE. | 144 // MAP_POPULATE. |
| 142 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. | 145 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. |
| 143 const uint32_t denied_mask = | 146 const uint32_t denied_mask = |
| 144 ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_NORESERVE | | 147 ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_NORESERVE | |
| (...skipping 20 matching lines...) Expand all Loading... |
| 165 // Glibc overrides the kernel's O_LARGEFILE value. Account for this. | 168 // Glibc overrides the kernel's O_LARGEFILE value. Account for this. |
| 166 int kOLargeFileFlag = O_LARGEFILE; | 169 int kOLargeFileFlag = O_LARGEFILE; |
| 167 if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips()) | 170 if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips()) |
| 168 kOLargeFileFlag = 0100000; | 171 kOLargeFileFlag = 0100000; |
| 169 | 172 |
| 170 const Arg<int> cmd(1); | 173 const Arg<int> cmd(1); |
| 171 const Arg<long> long_arg(2); | 174 const Arg<long> long_arg(2); |
| 172 | 175 |
| 173 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | | 176 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | |
| 174 kOLargeFileFlag | O_CLOEXEC | O_NOATIME); | 177 kOLargeFileFlag | O_CLOEXEC | O_NOATIME); |
| 175 return If(cmd == F_GETFL || cmd == F_GETFD || cmd == F_SETFD || | 178 return Switch(cmd) |
| 176 cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK || | 179 .CASES((F_GETFL, |
| 177 cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC || | 180 F_GETFD, |
| 178 (cmd == F_SETFL && (long_arg & denied_mask) == 0), | 181 F_SETFD, |
| 179 Allow()).Else(CrashSIGSYS()); | 182 F_SETLK, |
| 183 F_SETLKW, |
| 184 F_GETLK, |
| 185 F_DUPFD, |
| 186 F_DUPFD_CLOEXEC), |
| 187 Allow()) |
| 188 .Case(F_SETFL, |
| 189 If((long_arg & denied_mask) == 0, Allow()).Else(CrashSIGSYS())) |
| 190 .Default(CrashSIGSYS()); |
| 180 } | 191 } |
| 181 | 192 |
| 182 #if defined(__i386__) || defined(__mips__) | 193 #if defined(__i386__) || defined(__mips__) |
| 183 ResultExpr RestrictSocketcallCommand() { | 194 ResultExpr RestrictSocketcallCommand() { |
| 184 // Unfortunately, we are unable to restrict the first parameter to | 195 // Unfortunately, we are unable to restrict the first parameter to |
| 185 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very | 196 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very |
| 186 // few protocols actually support socketpair(2). The scary call that we're | 197 // few protocols actually support socketpair(2). The scary call that we're |
| 187 // worried about, socket(2), remains blocked. | 198 // worried about, socket(2), remains blocked. |
| 188 const Arg<int> call(0); | 199 const Arg<int> call(0); |
| 189 return If(call == SYS_SOCKETPAIR || call == SYS_SHUTDOWN || | 200 return Switch(call) |
| 190 call == SYS_RECV || call == SYS_SEND || | 201 .CASES((SYS_SOCKETPAIR, |
| 191 call == SYS_RECVFROM || call == SYS_SENDTO || | 202 SYS_SHUTDOWN, |
| 192 call == SYS_RECVMSG || call == SYS_SENDMSG, | 203 SYS_RECV, |
| 193 Allow()).Else(Error(EPERM)); | 204 SYS_SEND, |
| 205 SYS_RECVFROM, |
| 206 SYS_SENDTO, |
| 207 SYS_RECVMSG, |
| 208 SYS_SENDMSG), |
| 209 Allow()) |
| 210 .Default(Error(EPERM)); |
| 194 } | 211 } |
| 195 #endif | 212 #endif |
| 196 | 213 |
| 197 ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) { | 214 ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) { |
| 198 switch (sysno) { | 215 switch (sysno) { |
| 199 case __NR_kill: | 216 case __NR_kill: |
| 200 case __NR_tgkill: { | 217 case __NR_tgkill: { |
| 201 const Arg<pid_t> pid(0); | 218 const Arg<pid_t> pid(0); |
| 202 return If(pid == target_pid, Allow()).Else(CrashSIGSYSKill()); | 219 return If(pid == target_pid, Allow()).Else(CrashSIGSYSKill()); |
| 203 } | 220 } |
| 204 case __NR_tkill: | 221 case __NR_tkill: |
| 205 return CrashSIGSYSKill(); | 222 return CrashSIGSYSKill(); |
| 206 default: | 223 default: |
| 207 NOTREACHED(); | 224 NOTREACHED(); |
| 208 return CrashSIGSYS(); | 225 return CrashSIGSYS(); |
| 209 } | 226 } |
| 210 } | 227 } |
| 211 | 228 |
| 212 ResultExpr RestrictFutex() { | 229 ResultExpr RestrictFutex() { |
| 213 const int kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; | 230 const int kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; |
| 214 const int kOperationMask = ~kAllowedFutexFlags; | 231 const int kOperationMask = ~kAllowedFutexFlags; |
| 215 const int kAllowedFutexOperations[] = { | |
| 216 FUTEX_WAIT, FUTEX_WAKE, FUTEX_FD, FUTEX_REQUEUE, | |
| 217 FUTEX_CMP_REQUEUE, FUTEX_WAKE_OP, FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET}; | |
| 218 | 232 |
| 219 const Arg<int> op(1); | 233 const Arg<int> op(1); |
| 220 | 234 return Switch(op & kOperationMask) |
| 221 BoolExpr IsAllowedOp = (op & kOperationMask) == kAllowedFutexOperations[0]; | 235 .CASES((FUTEX_WAIT, |
| 222 for (size_t i = 1; i < arraysize(kAllowedFutexOperations); ++i) { | 236 FUTEX_WAKE, |
| 223 IsAllowedOp = | 237 FUTEX_FD, |
| 224 IsAllowedOp || ((op & kOperationMask) == kAllowedFutexOperations[i]); | 238 FUTEX_REQUEUE, |
| 225 } | 239 FUTEX_CMP_REQUEUE, |
| 226 return If(IsAllowedOp, Allow()).Else(CrashSIGSYSFutex()); | 240 FUTEX_WAKE_OP, |
| 241 FUTEX_WAIT_BITSET, |
| 242 FUTEX_WAKE_BITSET), |
| 243 Allow()) |
| 244 .Default(CrashSIGSYSFutex()); |
| 227 } | 245 } |
| 228 | 246 |
| 229 } // namespace sandbox. | 247 } // namespace sandbox. |
| OLD | NEW |