| 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.
|
|
|