root/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. RunningOnASAN
  2. IsArchitectureX86_64
  3. IsArchitectureI386
  4. RestrictCloneToThreadsAndEPERMFork
  5. RestrictPrctl
  6. RestrictIoctl
  7. RestrictMmapFlags
  8. RestrictMprotectFlags
  9. RestrictFcntlCommands
  10. RestrictSocketcallCommand

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

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(SandboxBPF* 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(SandboxBPF* 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(SandboxBPF* 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(SandboxBPF* 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(SandboxBPF* 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(SandboxBPF* 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(SandboxBPF* 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.

/* [<][>][^][v][top][bottom][index][help] */