Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  SandboxInfo.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "SandboxInfo.h"
#include "SandboxLogging.h"
#include "LinuxSched.h"

#include <errno.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>

#include "base/posix/eintr_wrapper.h"
#include "mozilla/Assertions.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/SandboxSettings.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"

#ifdef MOZ_VALGRIND
#  include <valgrind/valgrind.h>
#endif

// A note about assertions: in general, the worst thing this module
// should be able to do is disable sandboxing features, so release
// asserts or MOZ_CRASH should be avoided, even for seeming
// impossibilities like an unimplemented syscall returning success
// (which has happened: https://crbug.com/439795 ).
//
// MOZ_DIAGNOSTIC_ASSERT (debug builds, plus Nightly/Aurora non-debug)
// is probably the best choice for conditions that shouldn't be able
// to fail without the help of bugs in the kernel or system libraries.
//
// Regardless of assertion type, whatever condition caused it to fail
// should generally also disable the corresponding feature on builds
// that omit the assertion.

namespace mozilla {

static bool HasSeccompBPF() {
  // Allow simulating the absence of seccomp-bpf support, for testing.
  if (getenv("MOZ_FAKE_NO_SANDBOX")) {
    return false;
  }

  // Valgrind and the sandbox don't interact well, probably because Valgrind
  // does various system calls which aren't allowed, even if Firefox itself
  // is playing by the rules.
#if defined(MOZ_VALGRIND)
  if (RUNNING_ON_VALGRIND) {
    return false;
  }
#endif

  // Determine whether seccomp-bpf is supported by trying to
  // enable it with an invalid pointer for the filter.  This will
  // fail with EFAULT if supported and EINVAL if not, without
  // changing the process's state.

  int rv = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr);
  MOZ_DIAGNOSTIC_ASSERT(rv == -1,
                        "prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,"
                        " nullptr) didn't fail");
  MOZ_DIAGNOSTIC_ASSERT(errno == EFAULT || errno == EINVAL);
  return rv == -1 && errno == EFAULT;
}

static bool HasSeccompTSync() {
  // Similar to above, but for thread-sync mode.  See also Chromium's
  // sandbox::SandboxBPF::SupportsSeccompThreadFilterSynchronization
  if (getenv("MOZ_FAKE_NO_SECCOMP_TSYNC")) {
    return false;
  }
  int rv = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,
                   SECCOMP_FILTER_FLAG_TSYNC, nullptr);
  MOZ_DIAGNOSTIC_ASSERT(rv == -1,
                        "seccomp(..., SECCOMP_FILTER_FLAG_TSYNC,"
                        " nullptr) didn't fail");
  MOZ_DIAGNOSTIC_ASSERT(errno == EFAULT || errno == EINVAL || errno == ENOSYS);
  return rv == -1 && errno == EFAULT;
}

static bool HasUserNamespaceSupport() {
  // Note: the /proc/<pid>/ns/* files track setns(2) support, which in
  // some cases (e.g., pid) significantly postdates kernel support for
  // the namespace type, so in general this type of check could be a
  // false negative.  However, for user namespaces, any kernel new
  // enough for the feature to be usable for us has setns support
  // (v3.8), so this is okay.
  //
  // The non-user namespaces all default to "y" in init/Kconfig, but
  // check them explicitly in case someone has a weird custom config.
  static const charconst paths[] = {
      "/proc/self/ns/user",
      "/proc/self/ns/pid",
      "/proc/self/ns/net",
      "/proc/self/ns/ipc",
  };
  for (size_t i = 0; i < std::size(paths); ++i) {
    if (access(paths[i], F_OK) == -1) {
      MOZ_ASSERT(errno == ENOENT);
      return false;
    }
  }
  return true;
}

static bool CanCreateUserNamespace() {
  // Unfortunately, the only way to verify that this process can
  // create a new user namespace is to actually create one; because
  // this process's namespaces shouldn't be side-effected (yet), it's
  // necessary to clone (and collect) a child process.  See also
  // Chromium's sandbox::Credentials::SupportsNewUserNS.
  //
  // This is somewhat more expensive than the other tests, so it's
  // cached in the environment to prevent child processes from having
  // to re-run the test.
  //
  // This is run at static initializer time, while single-threaded, so
  // locking isn't needed to access the environment.
  static const char kCacheEnvName[] = "MOZ_ASSUME_USER_NS";
  const char* cached = getenv(kCacheEnvName);
  if (cached) {
    return cached[0] > '0';
  }

  // Bug 1434528: In addition to CLONE_NEWUSER, do something that uses
  // the new capabilities (in this case, cloning another namespace) to
  // detect AppArmor policies that allow CLONE_NEWUSER but don't allow
  // doing anything useful with it.
  //
  // Bug 1884347: There's a new AppArmor feature which can result in
  // unsharing NEWUSER and NEWPID (or NEWNET etc.) in one syscall
  // being allowed, but further use of capabilities will be blocked
  // afterwards.  That may be a bug, but we need to handle it.
  pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER, nullptr, nullptr,
                      nullptr, nullptr);
  if (pid == 0) {
    // The exact meaning of `unshare(CLONE_NEWPID)` is slightly
    // counterintuitive but in this case it doesn't matter.  This just
    // needs to be some operation that attempts to use capabilities,
    // to check if it's blocked by an LSM.
    int rv = unshare(CLONE_NEWPID);
    // Exit with status 0 on success, 1 on failure.
    _exit(rv == 0 ? 0 : 1);
  }
  if (pid == -1) {
    // Failure.
    MOZ_ASSERT(errno == EINVAL ||  // unsupported
               errno == EPERM ||   // root-only, or we're already chrooted
               errno == EUSERS);   // already at user namespace nesting limit
    setenv(kCacheEnvName, "0", 1);
    return false;
  }
  // Otherwise, in the parent and successful.
  int wstatus;
  bool waitpid_ok = HANDLE_EINTR(waitpid(pid, &wstatus, 0)) == pid;
  MOZ_ASSERT(waitpid_ok);
  if (!waitpid_ok) {
    return false;
  }
  // Check for failures reported by the child process.
  if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
    setenv(kCacheEnvName, "0", 1);
    return false;
  }
  setenv(kCacheEnvName, "1", 1);
  return true;
}

/* static */
MOZ_RUNINIT const SandboxInfo SandboxInfo::sSingleton = SandboxInfo();

SandboxInfo::SandboxInfo() {
  int flags = 0;
  static_assert(sizeof(flags) >= sizeof(Flags), "enum Flags fits in an int");

  if (HasSeccompBPF()) {
    flags |= kHasSeccompBPF;
    if (HasSeccompTSync()) {
      flags |= kHasSeccompTSync;
    }
  }

  if (HasUserNamespaceSupport()) {
    flags |= kHasPrivilegedUserNamespaces;
    if (CanCreateUserNamespace()) {
      flags |= kHasUserNamespaces;
    }
  }

  // We can't use mozilla::IsContentSandboxEnabled() here because a)
  // libmozsandbox can't depend on libxul, and b) this is called in a static
  // initializer before the prefences service is ready.
  if (!getenv("MOZ_DISABLE_CONTENT_SANDBOX")) {
    flags |= kEnabledForContent;
  }
  if (getenv("MOZ_PERMISSIVE_CONTENT_SANDBOX")) {
    flags |= kPermissive;
  }
  if (!getenv("MOZ_DISABLE_GMP_SANDBOX")) {
    flags |= kEnabledForMedia;
  }
  if (getenv("MOZ_SANDBOX_LOGGING")) {
    flags |= kVerbose;
  }
  if (getenv("MOZ_SANDBOX_LOGGING_FOR_TESTS")) {
    flags |= kVerboseTests;
  }

  mFlags = static_cast<Flags>(flags);
}

}  // namespace mozilla

Messung V0.5
C=84 H=95 G=89

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge