Example #1
0
/**
 * This is the SIGSYS handler function. It is used to report to the user
 * which system call has been denied by Seccomp.
 * This function also makes the process exit as denying the system call
 * will otherwise generally lead to unexpected behavior from the process,
 * since we don't know if all functions will handle such denials gracefully.
 *
 * @see InstallSyscallReporter() function.
 */
static void
Reporter(int nr, siginfo_t *info, void *void_context)
{
  ucontext_t *ctx = static_cast<ucontext_t*>(void_context);
  unsigned long syscall_nr, args[6];
  pid_t pid = getpid();

  if (nr != SIGSYS) {
    return;
  }
  if (info->si_code != SYS_SECCOMP) {
    return;
  }
  if (!ctx) {
    return;
  }

  syscall_nr = SECCOMP_SYSCALL(ctx);
  args[0] = SECCOMP_PARM1(ctx);
  args[1] = SECCOMP_PARM2(ctx);
  args[2] = SECCOMP_PARM3(ctx);
  args[3] = SECCOMP_PARM4(ctx);
  args[4] = SECCOMP_PARM5(ctx);
  args[5] = SECCOMP_PARM6(ctx);

#ifdef MOZ_GMP_SANDBOX
  if (syscall_nr == __NR_open && gMediaPluginFilePath) {
    const char *path = reinterpret_cast<const char*>(args[0]);
    int flags = int(args[1]);

    if ((flags & O_ACCMODE) != O_RDONLY) {
      SANDBOX_LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)",
                        path, flags);
    } else if (strcmp(path, gMediaPluginFilePath) != 0) {
      SANDBOX_LOG_ERROR("attempt to open file %s which is not the media plugin"
                        " %s", path, gMediaPluginFilePath);
    } else if (gMediaPluginFileDesc == -1) {
      SANDBOX_LOG_ERROR("multiple opens of media plugin file unimplemented");
    } else {
      SECCOMP_RESULT(ctx) = gMediaPluginFileDesc;
      gMediaPluginFileDesc = -1;
      return;
    }
  }
#endif

  SANDBOX_LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu,"
                    " args %lu %lu %lu %lu %lu %lu.  Killing process.",
                    pid, syscall_nr,
                    args[0], args[1], args[2], args[3], args[4], args[5]);

  // Bug 1017393: record syscall number somewhere useful.
  info->si_addr = reinterpret_cast<void*>(syscall_nr);

  gSandboxCrashFunc(nr, info, void_context);
  _exit(127);
}
Example #2
0
// Test whether a ucontext, interpreted as the state after a syscall,
// indicates the given error.  See also sandbox::Syscall::PutValueInUcontext.
static bool
ContextIsError(const ucontext_t *aContext, int aError)
{
    // Avoid integer promotion warnings.  (The unary addition makes
    // the decltype not evaluate to a reference type.)
    typedef decltype(+SECCOMP_RESULT(aContext)) reg_t;

#ifdef __mips__
    return SECCOMP_PARM4(aContext) != 0
           && SECCOMP_RESULT(aContext) == static_cast<reg_t>(aError);
#else
    return SECCOMP_RESULT(aContext) == static_cast<reg_t>(-aError);
#endif
}
Example #3
0
static void
Reporter(int nr, siginfo_t *info, void *void_context)
{
  ucontext_t *ctx = static_cast<ucontext_t*>(void_context);
  unsigned long syscall_nr, args[6];
  pid_t pid = getpid(), tid = syscall(__NR_gettid);

  if (nr != SIGSYS) {
    return;
  }
  if (info->si_code != SYS_SECCOMP) {
    return;
  }
  if (!ctx) {
    return;
  }

  syscall_nr = SECCOMP_SYSCALL(ctx);
  args[0] = SECCOMP_PARM1(ctx);
  args[1] = SECCOMP_PARM2(ctx);
  args[2] = SECCOMP_PARM3(ctx);
  args[3] = SECCOMP_PARM4(ctx);
  args[4] = SECCOMP_PARM5(ctx);
  args[5] = SECCOMP_PARM6(ctx);

  LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu"
            " %lu %lu %lu.  Killing process.", pid, syscall_nr,
            args[0], args[1], args[2], args[3], args[4], args[5]);

#ifdef MOZ_CRASHREPORTER
  bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
  if (!dumped) {
    LOG_ERROR("Failed to write minidump");
  }
#endif

  // Do this last, in case it crashes or deadlocks.
  SandboxLogJSStack();

  // Try to reraise, so the parent sees that this process crashed.
  // (If tgkill is forbidden, then seccomp will raise SIGSYS, which
  // also accomplishes that goal.)
  signal(SIGSYS, SIG_DFL);
  syscall(__NR_tgkill, pid, tid, nr);
  _exit(127);
}
Example #4
0
/**
 * This is the SIGSYS handler function.  It delegates to the Chromium
 * TrapRegistry handler (see InstallSigSysHandler, below) and, if the
 * trap handler installed by the policy would fail with ENOSYS,
 * crashes the process.  This allows unintentional policy failures to
 * be reported as crash dumps and fixed.  It also logs information
 * about the failed system call.
 *
 * Note that this could be invoked in parallel on multiple threads and
 * that it could be in async signal context (e.g., intercepting an
 * open() called from an async signal handler).
 */
static void
SigSysHandler(int nr, siginfo_t *info, void *void_context)
{
    ucontext_t *ctx = static_cast<ucontext_t*>(void_context);
    // This shouldn't ever be null, but the Chromium handler checks for
    // that and refrains from crashing, so let's not crash release builds:
    MOZ_DIAGNOSTIC_ASSERT(ctx);
    if (!ctx) {
        return;
    }

    // Save a copy of the context before invoking the trap handler,
    // which will overwrite one or more registers with the return value.
    ucontext_t savedCtx = *ctx;

    gChromiumSigSysHandler(nr, info, ctx);
    if (!ContextIsError(ctx, ENOSYS)) {
        return;
    }

    pid_t pid = getpid();
    unsigned long syscall_nr = SECCOMP_SYSCALL(&savedCtx);
    unsigned long args[6];
    args[0] = SECCOMP_PARM1(&savedCtx);
    args[1] = SECCOMP_PARM2(&savedCtx);
    args[2] = SECCOMP_PARM3(&savedCtx);
    args[3] = SECCOMP_PARM4(&savedCtx);
    args[4] = SECCOMP_PARM5(&savedCtx);
    args[5] = SECCOMP_PARM6(&savedCtx);

    // TODO, someday when this is enabled on MIPS: include the two extra
    // args in the error message.
    SANDBOX_LOG_ERROR("seccomp sandbox violation: pid %d, syscall %d,"
                      " args %d %d %d %d %d %d.  Killing process.",
                      pid, syscall_nr,
                      args[0], args[1], args[2], args[3], args[4], args[5]);

    // Bug 1017393: record syscall number somewhere useful.
    info->si_addr = reinterpret_cast<void*>(syscall_nr);

    gSandboxCrashFunc(nr, info, &savedCtx);
    _exit(127);
}
Example #5
0
/**
 * This is the SIGSYS handler function. It is used to report to the user
 * which system call has been denied by Seccomp.
 * This function also makes the process exit as denying the system call
 * will otherwise generally lead to unexpected behavior from the process,
 * since we don't know if all functions will handle such denials gracefully.
 *
 * @see InstallSyscallReporter() function.
 */
static void
Reporter(int nr, siginfo_t *info, void *void_context)
{
  ucontext_t *ctx = static_cast<ucontext_t*>(void_context);
  unsigned long syscall_nr, args[6];
  pid_t pid = getpid(), tid = syscall(__NR_gettid);

  if (nr != SIGSYS) {
    return;
  }
  if (info->si_code != SYS_SECCOMP) {
    return;
  }
  if (!ctx) {
    return;
  }

  syscall_nr = SECCOMP_SYSCALL(ctx);
  args[0] = SECCOMP_PARM1(ctx);
  args[1] = SECCOMP_PARM2(ctx);
  args[2] = SECCOMP_PARM3(ctx);
  args[3] = SECCOMP_PARM4(ctx);
  args[4] = SECCOMP_PARM5(ctx);
  args[5] = SECCOMP_PARM6(ctx);

#ifdef MOZ_GMP_SANDBOX
  if (syscall_nr == __NR_open && gMediaPluginFilePath) {
    const char *path = reinterpret_cast<const char*>(args[0]);
    int flags = int(args[1]);

    if ((flags & O_ACCMODE) != O_RDONLY) {
      LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)",
                path, flags);
    } else if (strcmp(path, gMediaPluginFilePath) != 0) {
      LOG_ERROR("attempt to open file %s which is not the media plugin %s",
                path, gMediaPluginFilePath);
    } else if (gMediaPluginFileDesc == -1) {
      LOG_ERROR("multiple opens of media plugin file unimplemented");
    } else {
      SECCOMP_RESULT(ctx) = gMediaPluginFileDesc;
      gMediaPluginFileDesc = -1;
      return;
    }
  }
#endif

  LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu"
            " %lu %lu %lu.  Killing process.", pid, syscall_nr,
            args[0], args[1], args[2], args[3], args[4], args[5]);

#ifdef MOZ_CRASHREPORTER
  // Bug 1017393: record syscall number somewhere useful.
  info->si_addr = reinterpret_cast<void*>(syscall_nr);
  bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
  if (!dumped) {
    LOG_ERROR("Failed to write minidump");
  }
#endif

  // Do this last, in case it crashes or deadlocks.
  SandboxLogJSStack();

  // Try to reraise, so the parent sees that this process crashed.
  // (If tgkill is forbidden, then seccomp will raise SIGSYS, which
  // also accomplishes that goal.)
  signal(SIGSYS, SIG_DFL);
  syscall(__NR_tgkill, pid, tid, nr);
  _exit(127);
}