Bug 1041886 - Separate Linux sandbox code into its own shared library. r=kang r=glandium

This creates libmozsandbox.so on builds that use sandboxing
(MOZ_CONTENT_SANDBOX or MOZ_GMP_SANDBOX).

The unavoidably libxul-dependent parts, for invoking the crash reporter
and printing the JS context, are separated into glue/SandboxCrash.cpp
and invoked via a callback.
This commit is contained in:
Jed Davis 2014-08-26 13:54:09 -07:00
Родитель e020caf2de
Коммит 23c21aa709
9 изменённых файлов: 189 добавлений и 73 удалений

Просмотреть файл

@ -744,6 +744,10 @@
; For process sandboxing
#if defined(XP_WIN)
@BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@
#elif defined(XP_LINUX)
#if defined(MOZ_CONTENT_SANDBOX) || defined(MOZ_GMP_SANDBOX)
@BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
#endif
#endif
; for Solaris SPARC

Просмотреть файл

@ -754,6 +754,10 @@
; For process sandboxing
#if defined(XP_WIN)
@BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@
#elif defined(XP_LINUX)
#if defined(MOZ_CONTENT_SANDBOX) || defined(MOZ_GMP_SANDBOX)
@BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
#endif
#endif
; for Solaris SPARC

Просмотреть файл

@ -544,6 +544,11 @@
@BINPATH@/chrome/pippki@JAREXT@
@BINPATH@/chrome/pippki.manifest
; For process sandboxing
#if defined(MOZ_CONTENT_SANDBOX) || defined(MOZ_GMP_SANDBOX)
@BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
#endif
; for Solaris SPARC
#ifdef SOLARIS
bin/libfreebl_32fpu_3.chk

Просмотреть файл

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Sandbox.h"
#include "SandboxInternal.h"
#include "SandboxLogging.h"
#include <unistd.h>
@ -25,13 +26,6 @@
#include "mozilla/Atomics.h"
#include "mozilla/NullPtr.h"
#include "mozilla/unused.h"
#include "mozilla/dom/Exceptions.h"
#include "nsThreadUtils.h"
#include "prenv.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#if defined(ANDROID)
#include "android_ucontext.h"
@ -45,6 +39,8 @@
namespace mozilla {
SandboxCrashFunc gSandboxCrashFunc;
#ifdef MOZ_GMP_SANDBOX
// For media plugins, we can start the sandbox before we dlopen the
// module, so we have to pre-open the file and simulate the sandboxed
@ -88,49 +84,6 @@ struct SandboxFlags {
static const SandboxFlags gSandboxFlags;
/**
* Log JS stack info in the same place as the sandbox violation
* message. Useful in case the responsible code is JS and all we have
* are logs and a minidump with the C++ stacks (e.g., on TBPL).
*/
static void
SandboxLogJSStack(void)
{
if (!NS_IsMainThread()) {
// This might be a worker thread... or it might be a non-JS
// thread, or a non-NSPR thread. There's isn't a good API for
// dealing with this, yet.
return;
}
nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
for (int i = 0; frame != nullptr; ++i) {
nsAutoString fileName, funName;
int32_t lineNumber;
// Don't stop unwinding if an attribute can't be read.
fileName.SetIsVoid(true);
unused << frame->GetFilename(fileName);
lineNumber = 0;
unused << frame->GetLineNumber(&lineNumber);
funName.SetIsVoid(true);
unused << frame->GetName(funName);
if (!funName.IsVoid() || !fileName.IsVoid()) {
SANDBOX_LOG_ERROR("JS frame %d: %s %s line %d", i,
funName.IsVoid() ?
"(anonymous)" : NS_ConvertUTF16toUTF8(funName).get(),
fileName.IsVoid() ?
"(no file)" : NS_ConvertUTF16toUTF8(fileName).get(),
lineNumber);
}
nsCOMPtr<nsIStackFrame> nextFrame;
nsresult rv = frame->GetCaller(getter_AddRefs(nextFrame));
NS_ENSURE_SUCCESS_VOID(rv);
frame = nextFrame;
}
}
/**
* This is the SIGSYS handler function. It is used to report to the user
* which system call has been denied by Seccomp.
@ -145,7 +98,7 @@ 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);
pid_t pid = getpid();
if (nr != SIGSYS) {
return;
@ -191,23 +144,10 @@ Reporter(int nr, siginfo_t *info, void *void_context)
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) {
SANDBOX_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);
gSandboxCrashFunc(nr, info, void_context);
_exit(127);
}
@ -338,7 +278,7 @@ BroadcastSetThreadSandbox(SandboxType aType)
DIR *taskdp;
struct dirent *de;
SandboxFilter filter(&sSetSandboxFilter, aType,
PR_GetEnv("MOZ_SANDBOX_VERBOSE"));
getenv("MOZ_SANDBOX_VERBOSE"));
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
"mozilla::Atomic<int> isn't represented by an int");
@ -469,6 +409,8 @@ BroadcastSetThreadSandbox(SandboxType aType)
static void
SetCurrentProcessSandbox(SandboxType aType)
{
MOZ_ASSERT(gSandboxCrashFunc);
if (InstallSyscallReporter()) {
SANDBOX_LOG_ERROR("install_syscall_reporter() failed\n");
}

Просмотреть файл

@ -7,6 +7,8 @@
#ifndef mozilla_Sandbox_h
#define mozilla_Sandbox_h
#include "mozilla/Types.h"
namespace mozilla {
// The Set*Sandbox() functions must not be called if the corresponding
@ -19,13 +21,13 @@ namespace mozilla {
#ifdef MOZ_CONTENT_SANDBOX
// Disabled by setting env var MOZ_DISABLE_CONTENT_SANDBOX.
bool CanSandboxContentProcess();
void SetContentProcessSandbox();
MFBT_API bool CanSandboxContentProcess();
MFBT_API void SetContentProcessSandbox();
#endif
#ifdef MOZ_GMP_SANDBOX
// Disabled by setting env var MOZ_DISABLE_GMP_SANDBOX.
bool CanSandboxMediaPlugin();
void SetMediaPluginSandbox(const char *aFilePath);
MFBT_API bool CanSandboxMediaPlugin();
MFBT_API void SetMediaPluginSandbox(const char *aFilePath);
#endif
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,24 @@
/* -*- 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/. */
#ifndef mozilla_SandboxInternal_h
#define mozilla_SandboxInternal_h
// The code in Sandbox.cpp can't link against libxul, where
// SandboxCrash.cpp lives, so it has to use a callback, defined here.
#include <signal.h>
#include "mozilla/Types.h"
namespace mozilla {
typedef void (*SandboxCrashFunc)(int, siginfo_t*, void*);
extern MFBT_API SandboxCrashFunc gSandboxCrashFunc;
} // namespace mozilla
#endif // mozilla_SandboxInternal_h

Просмотреть файл

@ -0,0 +1,99 @@
/* -*- 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/. */
// This file needs to be linked into libxul, so it can access the JS
// stack and the crash reporter. Everything else in this directory
// should be able to be linked into its own shared library, in order
// to be able to isolate sandbox/chromium from ipc/chromium.
#include "SandboxInternal.h"
#include "SandboxLogging.h"
#include <unistd.h>
#include <sys/syscall.h>
#include "mozilla/NullPtr.h"
#include "mozilla/unused.h"
#include "mozilla/dom/Exceptions.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
namespace mozilla {
// Log JS stack info in the same place as the sandbox violation
// message. Useful in case the responsible code is JS and all we have
// are logs and a minidump with the C++ stacks (e.g., on TBPL).
static void
SandboxLogJSStack(void)
{
if (!NS_IsMainThread()) {
// This might be a worker thread... or it might be a non-JS
// thread, or a non-NSPR thread. There's isn't a good API for
// dealing with this, yet.
return;
}
nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
for (int i = 0; frame != nullptr; ++i) {
nsAutoString fileName, funName;
int32_t lineNumber;
// Don't stop unwinding if an attribute can't be read.
fileName.SetIsVoid(true);
unused << frame->GetFilename(fileName);
lineNumber = 0;
unused << frame->GetLineNumber(&lineNumber);
funName.SetIsVoid(true);
unused << frame->GetName(funName);
if (!funName.IsVoid() || !fileName.IsVoid()) {
SANDBOX_LOG_ERROR("JS frame %d: %s %s line %d", i,
funName.IsVoid() ?
"(anonymous)" : NS_ConvertUTF16toUTF8(funName).get(),
fileName.IsVoid() ?
"(no file)" : NS_ConvertUTF16toUTF8(fileName).get(),
lineNumber);
}
nsCOMPtr<nsIStackFrame> nextFrame;
nsresult rv = frame->GetCaller(getter_AddRefs(nextFrame));
NS_ENSURE_SUCCESS_VOID(rv);
frame = nextFrame;
}
}
static void
SandboxCrash(int nr, siginfo_t *info, void *void_context)
{
pid_t pid = getpid(), tid = syscall(__NR_gettid);
#ifdef MOZ_CRASHREPORTER
bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
if (!dumped) {
SANDBOX_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);
}
static void __attribute__((constructor))
SandboxSetCrashFunc()
{
gSandboxCrashFunc = SandboxCrash;
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,21 @@
# -*- Mode: python; python-indent: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
FAIL_ON_WARNINGS = True
SOURCES += [
'SandboxCrash.cpp',
]
LOCAL_INCLUDES += [
'/security/sandbox/linux',
]
USE_LIBS += [
'mozsandbox',
]
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -6,6 +6,9 @@
FAIL_ON_WARNINGS = True
LIBRARY_NAME = 'mozsandbox'
FORCE_SHARED_LIB = True
EXPORTS.mozilla += [
'Sandbox.h',
]
@ -18,8 +21,20 @@ SOURCES += [
'SandboxFilter.cpp',
]
LOCAL_INCLUDES += ['/security/sandbox/chromium']
DEFINES['NS_NO_XPCOM'] = True
DISABLE_STL_WRAPPING = True
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/security/sandbox',
'/security/sandbox/chromium',
]
FINAL_LIBRARY = 'xul'
if CONFIG['OS_TARGET'] != 'Android':
# Needed for clock_gettime with glibc < 2.17:
OS_LIBS += [
'rt',
]
DIRS += [
'glue',
]