mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
f71f515508
- Bug 1141906 - Adjust some assertions in Linux sandbox feature detection. r=kang (365e9a6a8e) - bug 1169408 - Merge mozButtonAccessible and mozPopupButtonAccessible r=surkov (6996bb22e8) - Bug 1162434 - Make windows emulation work on X64, r=marcoz (f0bb96de8a) - Bug 1162434 part 2 - Fix ISimpleDOMNode Unique ID on 64 bit systems, r=surkov (1afbaa9fec) - code style (3cabaf0882) - Bug 734229 - Partially address by refusing to re-negotiate on NTLM. r=mayhemer, r=keeler (59b7feea33) - Bug 1164714 - Move netwerk/base/nsISiteSecurityService.idl into security/manager/ssl. r=keeler,mcmanus (154e93a29c) - Bug 1164714 - Move netwerk/test/TestSTSParser.cpp into security/manager/ssl/tests/. r=keeler (7fc68a2b66) - Bug 1124649 - Part 1 - Add specific error messages for various types of STS and PKP header failures. r=keeler,hurley (e967aef5fc) - Bug 1046421 - Do not disclose the system hostname via NTLM handler. r=honzab (a4a85439ca) - Bug 1084025 - Add telemetry to measure failures due to not falling back. r=keeler (5388e21c64) - Bug 1106470 - Drop SSLv3 support entirely from PSM. r=keeler (5de896acc0) - Bug 1195606 - Use channel->ascynOpen2 in security/manager/ssl/nsNSSCallbacks.cpp (r=sicking) (8b5e18f069) - Bug 1197644 - Remove the security.ssl.warn_missing_rfc5746 pref. r=keeler (f76ae9af3e) - namespace (7817663683)
200 lines
6.4 KiB
C++
200 lines
6.4 KiB
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 "LinuxSched.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <sys/prctl.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 "sandbox/linux/seccomp-bpf/linux_seccomp.h"
|
|
#include "sandbox/linux/services/linux_syscalls.h"
|
|
|
|
// 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;
|
|
}
|
|
// 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 char* const paths[] = {
|
|
"/proc/self/ns/user",
|
|
"/proc/self/ns/pid",
|
|
"/proc/self/ns/net",
|
|
"/proc/self/ns/ipc",
|
|
};
|
|
for (size_t i = 0; i < ArrayLength(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';
|
|
}
|
|
|
|
// Valgrind might allow the clone, but doesn't know what to do with
|
|
// unshare. Check for that by unsharing nothing. (Valgrind will
|
|
// probably need sandboxing disabled entirely, but no need to break
|
|
// things worse than strictly necessary.)
|
|
if (syscall(__NR_unshare, 0) != 0) {
|
|
#ifdef MOZ_VALGRIND
|
|
MOZ_ASSERT(errno == ENOSYS);
|
|
#else
|
|
// If something else can cause that call to fail, we's like to know
|
|
// about it; the right way to handle it might not be the same.
|
|
MOZ_ASSERT(false);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER,
|
|
nullptr, nullptr, nullptr, nullptr);
|
|
if (pid == 0) {
|
|
// In the child. Do as little as possible.
|
|
_exit(0);
|
|
}
|
|
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.
|
|
bool waitpid_ok = HANDLE_EINTR(waitpid(pid, nullptr, 0)) == pid;
|
|
MOZ_ASSERT(waitpid_ok);
|
|
if (!waitpid_ok) {
|
|
return false;
|
|
}
|
|
setenv(kCacheEnvName, "1", 1);
|
|
return true;
|
|
}
|
|
|
|
/* static */
|
|
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;
|
|
}
|
|
}
|
|
|
|
#ifdef MOZ_CONTENT_SANDBOX
|
|
if (!getenv("MOZ_DISABLE_CONTENT_SANDBOX")) {
|
|
flags |= kEnabledForContent;
|
|
}
|
|
#endif
|
|
#ifdef MOZ_GMP_SANDBOX
|
|
if (!getenv("MOZ_DISABLE_GMP_SANDBOX")) {
|
|
flags |= kEnabledForMedia;
|
|
}
|
|
#endif
|
|
if (getenv("MOZ_SANDBOX_VERBOSE")) {
|
|
flags |= kVerbose;
|
|
}
|
|
|
|
mFlags = static_cast<Flags>(flags);
|
|
}
|
|
|
|
} // namespace mozilla
|