mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
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:
parent
e020caf2de
commit
23c21aa709
@ -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
|
||||
|
24
security/sandbox/linux/SandboxInternal.h
Normal file
24
security/sandbox/linux/SandboxInternal.h
Normal file
@ -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
|
99
security/sandbox/linux/glue/SandboxCrash.cpp
Normal file
99
security/sandbox/linux/glue/SandboxCrash.cpp
Normal file
@ -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
|
21
security/sandbox/linux/glue/moz.build
Normal file
21
security/sandbox/linux/glue/moz.build
Normal file
@ -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',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user