Index: sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c26cfd835c1873f9192c20b3d991fd7839a85a6c |
--- /dev/null |
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc |
@@ -0,0 +1,218 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" |
+ |
+#include <errno.h> |
+#include <fcntl.h> |
+#include <fcntl.h> |
+#include <linux/net.h> |
+#include <sched.h> |
+#include <signal.h> |
+#include <sys/ioctl.h> |
+#include <sys/mman.h> |
+#include <sys/prctl.h> |
+#include <sys/stat.h> |
+#include <sys/types.h> |
+#include <unistd.h> |
+ |
+#include "base/basictypes.h" |
+#include "base/logging.h" |
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
+#include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
+ |
+#if defined(OS_ANDROID) |
+#if !defined(F_DUPFD_CLOEXEC) |
+#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6) |
+#endif |
+#endif |
+ |
+#if defined(__arm__) && !defined(MAP_STACK) |
+#define MAP_STACK 0x20000 // Daisy build environment has old headers. |
+#endif |
+ |
+using playground2::arch_seccomp_data; |
+using playground2::ErrorCode; |
+using playground2::Sandbox; |
+ |
+namespace { |
+ |
+inline bool RunningOnASAN() { |
+#if defined(ADDRESS_SANITIZER) |
+ return true; |
+#else |
+ return false; |
+#endif |
+} |
+ |
+inline bool IsArchitectureX86_64() { |
+#if defined(__x86_64__) |
+ return true; |
+#else |
+ return false; |
+#endif |
+} |
+ |
+inline bool IsArchitectureI386() { |
+#if defined(__i386__) |
+ return true; |
+#else |
+ return false; |
+#endif |
+} |
+ |
+} // namespace. |
+ |
+namespace sandbox { |
+ |
+ErrorCode RestrictCloneToThreadsAndEPERMFork(Sandbox* sandbox) { |
+ // Glibc's pthread. |
+ if (!RunningOnASAN()) { |
+ return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
+ CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ CLONE_PARENT_SETTID | SIGCHLD, |
+ ErrorCode(EPERM), |
+ // ARM |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, |
+ ErrorCode(EPERM), |
+ sandbox->Trap(SIGSYSCloneFailure, NULL)))); |
+ } else { |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ } |
+} |
+ |
+ErrorCode RestrictPrctl(Sandbox* sandbox) { |
+ // Will need to add seccomp compositing in the future. PR_SET_PTRACER is |
+ // used by breakpad but not needed anymore. |
+ return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Trap(SIGSYSPrctlFailure, NULL)))); |
+} |
+ |
+ErrorCode RestrictIoctl(Sandbox* sandbox) { |
+ return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Trap(SIGSYSIoctlFailure, NULL))); |
+} |
+ |
+ErrorCode RestrictMmapFlags(Sandbox* sandbox) { |
+ // The flags you see are actually the allowed ones, and the variable is a |
+ // "denied" mask because of the negation operator. |
+ // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as |
+ // MAP_POPULATE. |
+ // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. |
+ uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | |
+ MAP_STACK | MAP_NORESERVE | MAP_FIXED | |
+ MAP_DENYWRITE); |
+ return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
+ denied_mask, |
+ sandbox->Trap(CrashSIGSYS_Handler, NULL), |
+ ErrorCode(ErrorCode::ERR_ALLOWED)); |
+} |
+ |
+ErrorCode RestrictMprotectFlags(Sandbox* sandbox) { |
+ // The flags you see are actually the allowed ones, and the variable is a |
+ // "denied" mask because of the negation operator. |
+ // Significantly, we don't permit weird undocumented flags such as |
+ // PROT_GROWSDOWN. |
+ uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC); |
+ return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
+ denied_mask, |
+ sandbox->Trap(CrashSIGSYS_Handler, NULL), |
+ ErrorCode(ErrorCode::ERR_ALLOWED)); |
+} |
+ |
+ErrorCode RestrictFcntlCommands(Sandbox* sandbox) { |
+ // We also restrict the flags in F_SETFL. We don't want to permit flags with |
+ // a history of trouble such as O_DIRECT. The flags you see are actually the |
+ // allowed ones, and the variable is a "denied" mask because of the negation |
+ // operator. |
+ // Glibc overrides the kernel's O_LARGEFILE value. Account for this. |
+ int kOLargeFileFlag = O_LARGEFILE; |
+ if (IsArchitectureX86_64() || IsArchitectureI386()) |
+ kOLargeFileFlag = 0100000; |
+ |
+ // TODO(jln): add TP_LONG/TP_SIZET types. |
+ ErrorCode::ArgType mask_long_type; |
+ if (sizeof(long) == 8) |
+ mask_long_type = ErrorCode::TP_64BIT; |
+ else if (sizeof(long) == 4) |
+ mask_long_type = ErrorCode::TP_32BIT; |
+ else |
+ NOTREACHED(); |
+ |
+ unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | |
+ kOLargeFileFlag | O_CLOEXEC | O_NOATIME); |
+ return sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_GETFL, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_SETFL, |
+ sandbox->Cond(2, mask_long_type, |
+ ErrorCode::OP_HAS_ANY_BITS, denied_mask, |
+ sandbox->Trap(CrashSIGSYS_Handler, NULL), |
+ ErrorCode(ErrorCode::ERR_ALLOWED)), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_GETFD, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_SETFD, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_DUPFD, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_SETLK, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_SETLKW, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_GETLK, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(1, ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC, |
+ ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Trap(CrashSIGSYS_Handler, NULL)))))))))); |
+} |
+ |
+#if defined(__i386__) |
+ErrorCode RestrictSocketcallCommand(Sandbox* sandbox) { |
+ // Unfortunately, we are unable to restrict the first parameter to |
+ // socketpair(2). Whilst initially sounding bad, it's noteworthy that very |
+ // few protocols actually support socketpair(2). The scary call that we're |
+ // worried about, socket(2), remains blocked. |
+ return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
+ SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED), |
+ ErrorCode(EPERM))))))))); |
+} |
+#endif |
+ |
+} // namespace sandbox. |