Bug 1236108: Backout 34a219cbd67d; r=backout a=lizzard

MozReview-Commit-ID: EEYLmdZrZmN
This commit is contained in:
Aaron Klotz 2016-03-28 12:41:48 -06:00
parent c9c9658327
commit 6a3b9aff95
9 changed files with 549 additions and 147 deletions

View File

@ -12,8 +12,13 @@
#include "mozilla/WindowsVersion.h"
#endif
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
#include <stdlib.h>
#endif
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
#include "mozilla/Preferences.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#endif
@ -33,12 +38,21 @@ IsSandboxTempDirRequired()
(Preferences::GetInt("security.sandbox.content.level") >= 1));
}
static const char*
SandboxTempDirParent()
static void
SetTmpEnvironmentVariable(nsIFile* aValue)
{
// On Windows, the sandbox-writable temp directory resides in the
// low integrity sandbox base directory.
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
// Save the TMP environment variable so that is is picked up by GetTempPath().
// Note that we specifically write to the TMP variable, as that is the first
// variable that is checked by GetTempPath() to determine its output.
nsAutoString fullTmpPath;
nsresult rv = aValue->GetPath(fullTmpPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
// We also set TEMP in case there is naughty third-party code that is
// referencing the environment variable directly.
NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
}
#endif
@ -50,10 +64,15 @@ IsSandboxTempDirRequired()
return (Preferences::GetInt("security.sandbox.content.level") >= 1);
}
static const char*
SandboxTempDirParent()
static void
SetTmpEnvironmentVariable(nsIFile* aValue)
{
return NS_OS_TEMP_DIR;
nsAutoCString fullTmpPath;
nsresult rv = aValue->GetNativePath(fullTmpPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
NS_WARN_IF(setenv("TMPDIR", fullTmpPath.get(), 1) != 0);
}
#endif
@ -68,24 +87,11 @@ SetUpSandboxEnvironment()
return;
}
nsAdoptingString tempDirSuffix =
Preferences::GetString("security.sandbox.content.tempDirSuffix");
if (tempDirSuffix.IsEmpty()) {
NS_WARNING("Sandbox-writable temp directory suffix pref not set.");
return;
}
// Get the parent of our sandbox writable temp directory.
nsCOMPtr<nsIFile> lowIntegrityTemp;
nsresult rv = nsDirectoryService::gService->Get(SandboxTempDirParent(),
NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Append our profile specific temp name.
rv = lowIntegrityTemp->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
nsCOMPtr<nsIFile> sandboxedContentTemp;
nsresult rv =
nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(sandboxedContentTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
@ -93,10 +99,12 @@ SetUpSandboxEnvironment()
// Change the gecko defined temp directory to our sandbox-writable one.
// Undefine returns a failure if the property is not already set.
Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
SetTmpEnvironmentVariable(sandboxedContentTemp);
}
#endif

View File

@ -5,6 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsExceptionHandler.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDataHashtable.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/dom/CrashReporterChild.h"
@ -121,8 +124,7 @@ typedef std::wstring xpstring;
#define CRASH_REPORTER_FILENAME "crashreporter.exe"
#define PATH_SEPARATOR "\\"
#define XP_PATH_SEPARATOR L"\\"
// sort of arbitrary, but MAX_PATH is kinda small
#define XP_PATH_MAX 4096
#define XP_PATH_MAX (MAX_PATH + 1)
// "<reporter path>" "<minidump path>"
#define CMDLINE_SIZE ((XP_PATH_MAX * 2) + 6)
#ifdef _USE_32BIT_TIME_T
@ -157,10 +159,17 @@ typedef std::string xpstring;
#endif
#endif // XP_WIN32
#if defined(__GNUC__)
#define MAYBE_UNUSED __attribute__((unused))
#else
#define MAYBE_UNUSED
#endif // defined(__GNUC__)
#ifndef XP_LINUX
static const XP_CHAR dumpFileExtension[] = XP_TEXT(".dmp");
#endif
static const XP_CHAR childCrashAnnotationBaseName[] = XP_TEXT("GeckoChildCrash");
static const XP_CHAR extraFileExtension[] = XP_TEXT(".extra");
static const XP_CHAR memoryReportExtension[] = XP_TEXT(".memory.json.gz");
@ -258,6 +267,11 @@ static bool isSafeToDump = false;
// OOP crash reporting
static CrashGenerationServer* crashServer; // chrome process has this
#if (defined(XP_MACOSX) || defined(XP_WIN)) && defined(MOZ_CONTENT_SANDBOX)
// This field is only valid in the chrome process, not content.
static xpstring* contentProcessTmpDir = nullptr;
#endif
# if defined(XP_WIN) || defined(XP_MACOSX)
// If crash reporting is disabled, we hand out this "null" pipe to the
// child process and don't attempt to connect to a parent server.
@ -489,12 +503,34 @@ CreateFileFromPath(const wchar_t* path, nsIFile** file)
{
CreateFileFromPath(std::wstring(path), file);
}
static xpstring*
CreatePathFromFile(nsIFile* file)
{
nsAutoString path;
nsresult rv = file->GetPath(path);
if (NS_FAILED(rv)) {
return nullptr;
}
return new xpstring(path.get(), path.Length());
}
#else
static void
CreateFileFromPath(const xpstring& path, nsIFile** file)
{
NS_NewNativeLocalFile(nsDependentCString(path.c_str()), false, file);
}
MAYBE_UNUSED static xpstring*
CreatePathFromFile(nsIFile* file)
{
nsAutoCString path;
nsresult rv = file->GetNativePath(path);
if (NS_FAILED(rv)) {
return nullptr;
}
return new xpstring(path.get(), path.Length());
}
#endif
static XP_CHAR*
@ -583,6 +619,7 @@ bool copy_file(const char* from, const char* to)
#endif
#ifdef XP_WIN
class PlatformWriter
{
public:
@ -701,6 +738,34 @@ WriteAnnotation(PlatformWriter& pw, const char (&name)[N],
WriteLiteral(pw, "\n");
};
/**
* If minidump_id is null, we assume that dump_path contains the full
* dump file path.
*/
static void
OpenAPIData(PlatformWriter& aWriter,
const XP_CHAR* dump_path, const XP_CHAR* minidump_id = nullptr
)
{
static XP_CHAR extraDataPath[XP_PATH_MAX];
int size = XP_PATH_MAX;
XP_CHAR* p;
if (minidump_id) {
p = Concat(extraDataPath, dump_path, &size);
p = Concat(p, XP_PATH_SEPARATOR, &size);
p = Concat(p, minidump_id, &size);
} else {
p = Concat(extraDataPath, dump_path, &size);
// Skip back past the .dmp extension, if any.
if (*(p - 4) == XP_TEXT('.')) {
p -= 4;
size += 4;
}
}
Concat(p, extraFileExtension, &size);
aWriter.Open(extraDataPath);
}
bool MinidumpCallback(
#ifdef XP_LINUX
const MinidumpDescriptor& descriptor,
@ -729,19 +794,6 @@ bool MinidumpCallback(
Concat(minidumpPath, descriptor.path(), &size);
#endif
static XP_CHAR extraDataPath[XP_PATH_MAX];
size = XP_PATH_MAX;
#ifndef XP_LINUX
p = Concat(extraDataPath, dump_path, &size);
p = Concat(p, XP_PATH_SEPARATOR, &size);
p = Concat(p, minidump_id, &size);
#else
p = Concat(extraDataPath, descriptor.path(), &size);
// Skip back past the .dmp extension.
p -= 4;
#endif
Concat(p, extraFileExtension, &size);
static XP_CHAR memoryReportLocalPath[XP_PATH_MAX];
size = XP_PATH_MAX;
#ifndef XP_LINUX
@ -866,7 +918,11 @@ bool MinidumpCallback(
if (!crashReporterAPIData->IsEmpty()) {
// write out API data
apiData.Open(extraDataPath);
#ifdef XP_LINUX
OpenAPIData(apiData, descriptor.path());
#else
OpenAPIData(apiData, dump_path, minidump_id);
#endif
apiData.WriteBuffer(crashReporterAPIData->get(), crashReporterAPIData->Length());
}
WriteAnnotation(apiData, "CrashTime", crashTimeString);
@ -1058,6 +1114,154 @@ bool MinidumpCallback(
return returnValue;
}
#if defined(XP_MACOSX) || defined(__ANDROID__)
static size_t
EnsureTrailingSlash(char* aBuf, size_t aBufLen)
{
size_t len = XP_STRLEN(aBuf);
if ((len + 2) < aBufLen && aBuf[len - 1] != '/') {
aBuf[len] = '/';
++len;
aBuf[len] = 0;
}
return len;
}
#endif
#if defined(XP_WIN32)
static size_t
BuildTempPath(wchar_t* aBuf, size_t aBufLen)
{
// first figure out buffer size
DWORD pathLen = GetTempPath(0, nullptr);
if (pathLen == 0 || pathLen >= aBufLen) {
return 0;
}
return GetTempPath(pathLen, aBuf);
}
#elif defined(XP_MACOSX)
static size_t
BuildTempPath(char* aBuf, size_t aBufLen)
{
if (aBufLen < PATH_MAX) {
return 0;
}
FSRef fsRef;
OSErr err = FSFindFolder(kUserDomain, kTemporaryFolderType,
kCreateFolder, &fsRef);
if (err != noErr) {
return 0;
}
OSStatus status = FSRefMakePath(&fsRef, (UInt8*)aBuf, PATH_MAX);
if (status != noErr) {
return 0;
}
return EnsureTrailingSlash(aBuf, aBufLen);
}
#elif defined(__ANDROID__)
static size_t
BuildTempPath(char* aBuf, size_t aBufLen)
{
// GeckoAppShell or Gonk's init.rc sets this in the environment
const char *tempenv = PR_GetEnv("TMPDIR");
if (!tempenv) {
return false;
}
int size = (int)aBufLen;
Concat(aBuf, tempenv, &size);
return EnsureTrailingSlash(aBuf, aBufLen);
}
#elif defined(XP_UNIX)
static size_t
BuildTempPath(char* aBuf, size_t aBufLen)
{
// we assume it's always /tmp on unix systems
NS_NAMED_LITERAL_CSTRING(tmpPath, "/tmp/");
int size = (int)aBufLen;
Concat(aBuf, tmpPath.get(), &size);
return tmpPath.Length();
}
#else
#error "Implement this for your platform"
#endif
template <typename CharT, size_t N>
static size_t
BuildTempPath(CharT (&aBuf)[N])
{
static_assert(N >= XP_PATH_MAX, "char array length is too small");
return BuildTempPath(&aBuf[0], N);
}
template <typename PathStringT>
static bool
BuildTempPath(PathStringT& aResult)
{
aResult.SetLength(XP_PATH_MAX);
size_t actualLen = BuildTempPath(aResult.BeginWriting(), XP_PATH_MAX);
if (!actualLen) {
return false;
}
aResult.SetLength(actualLen);
return true;
}
static void
PrepareChildExceptionTimeAnnotations()
{
MOZ_ASSERT(!XRE_IsParentProcess());
static XP_CHAR tempPath[XP_PATH_MAX] = {0};
// Get the temp path
size_t tempPathLen = BuildTempPath(tempPath);
if (!tempPathLen) {
return;
}
// Generate and append the file name
int size = XP_PATH_MAX - tempPathLen;
XP_CHAR* p = tempPath + tempPathLen;
p = Concat(p, childCrashAnnotationBaseName, &size);
XP_CHAR pidBuffer[32] = XP_TEXT("");
#if defined(XP_WIN32)
_ui64tow(GetCurrentProcessId(), pidBuffer, 10);
#else
XP_STOA(getpid(), pidBuffer, 10);
#endif
p = Concat(p, pidBuffer, &size);
// Now open the file...
PlatformWriter apiData;
OpenAPIData(apiData, tempPath);
// ...and write out any annotations. These should be escaped if necessary
// (but don't call EscapeAnnotation here, because it touches the heap).
char oomAllocationSizeBuffer[32] = "";
if (gOOMAllocationSize) {
XP_STOA(gOOMAllocationSize, oomAllocationSizeBuffer, 10);
}
if (oomAllocationSizeBuffer[0]) {
WriteAnnotation(apiData, "OOMAllocationSize", oomAllocationSizeBuffer);
}
if (gMozCrashReason) {
WriteAnnotation(apiData, "MozCrashReason", gMozCrashReason);
}
}
#ifdef XP_WIN
static void
ReserveBreakpadVM()
@ -1108,6 +1312,18 @@ static bool FPEFilter(void* context, EXCEPTION_POINTERS* exinfo,
FreeBreakpadVM();
return true;
}
static bool
ChildFPEFilter(void* context, EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion)
{
bool result = FPEFilter(context, exinfo, assertion);
if (result) {
PrepareChildExceptionTimeAnnotations();
}
return result;
}
#endif // XP_WIN
static bool ShouldReport()
@ -1127,13 +1343,22 @@ static bool ShouldReport()
return true;
}
namespace {
bool Filter(void* context) {
mozilla::IOInterposer::Disable();
return true;
}
static bool
Filter(void* context)
{
mozilla::IOInterposer::Disable();
return true;
}
static bool
ChildFilter(void* context)
{
bool result = Filter(context);
if (result) {
PrepareChildExceptionTimeAnnotations();
}
return result;
}
nsresult SetExceptionHandler(nsIFile* aXREDirectory,
bool force/*=false*/)
@ -1228,41 +1453,12 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
// get temp path to use for minidump path
#if defined(XP_WIN32)
nsString tempPath;
// first figure out buffer size
int pathLen = GetTempPath(0, nullptr);
if (pathLen == 0)
return NS_ERROR_FAILURE;
tempPath.SetLength(pathLen);
GetTempPath(pathLen, (LPWSTR)tempPath.BeginWriting());
#elif defined(XP_MACOSX)
nsCString tempPath;
FSRef fsRef;
OSErr err = FSFindFolder(kUserDomain, kTemporaryFolderType,
kCreateFolder, &fsRef);
if (err != noErr)
return NS_ERROR_FAILURE;
char path[PATH_MAX];
OSStatus status = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
if (status != noErr)
return NS_ERROR_FAILURE;
tempPath = path;
#elif defined(__ANDROID__)
// GeckoAppShell or Gonk's init.rc sets this in the environment
const char *tempenv = PR_GetEnv("TMPDIR");
if (!tempenv)
return NS_ERROR_FAILURE;
nsCString tempPath(tempenv);
#elif defined(XP_UNIX)
// we assume it's always /tmp on unix systems
nsCString tempPath = NS_LITERAL_CSTRING("/tmp/");
#else
#error "Implement this for your platform"
nsCString tempPath;
#endif
if (!BuildTempPath(tempPath)) {
return NS_ERROR_FAILURE;
}
#ifdef XP_MACOSX
// Initialize spawn attributes, since this calls malloc.
@ -2704,24 +2900,164 @@ AppendExtraData(nsIFile* extraFile, const AnnotationTable& data)
return WriteExtraData(extraFile, data, Blacklist());
}
static bool
GetExtraFileForChildPid(nsIFile* aMinidump, uint32_t aPid, nsIFile** aExtraFile)
{
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIFile> extraFile;
nsresult rv;
#if defined(XP_WIN) || defined(XP_MACOSX)
# if defined(MOZ_CONTENT_SANDBOX)
if (!contentProcessTmpDir) {
return false;
}
CreateFileFromPath(*contentProcessTmpDir, getter_AddRefs(extraFile));
if (!extraFile) {
return false;
}
# else
rv = aMinidump->Clone(getter_AddRefs(extraFile));
if (NS_FAILED(rv)) {
return false;
}
# endif // defined(MOZ_CONTENT_SANDBOX)
#elif defined(XP_UNIX)
rv = NS_NewLocalFile(NS_LITERAL_STRING("/tmp"), false,
getter_AddRefs(extraFile));
if (NS_FAILED(rv)) {
return false;
}
#else
#error "Implement this for your platform"
#endif
nsAutoString leafName;
#if defined(XP_WIN)
leafName.AppendPrintf("%S%u%S", childCrashAnnotationBaseName, aPid,
extraFileExtension);
#else
leafName.AppendPrintf("%s%u%s", childCrashAnnotationBaseName, aPid,
extraFileExtension);
#endif
#if defined(XP_WIN) || defined(XP_MACOSX)
# if defined(MOZ_CONTENT_SANDBOX)
rv = extraFile->Append(leafName);
if (NS_FAILED(rv)) {
return false;
}
# else
rv = extraFile->SetLeafName(leafName);
if (NS_FAILED(rv)) {
return false;
}
# endif // defined(MOZ_CONTENT_SANDBOX)
#elif defined(XP_UNIX)
rv = extraFile->Append(leafName);
if (NS_FAILED(rv)) {
return false;
}
#else
#error "Implement this for your platform"
#endif
extraFile.forget(aExtraFile);
return true;
}
static bool
IsDataEscaped(char* aData)
{
if (strchr(aData, '\n')) {
// There should not be any newlines
return false;
}
char* pos = aData;
while ((pos = strchr(pos, '\\'))) {
if (*(pos + 1) != '\\') {
return false;
}
// Add 2 to account for the second pos
pos += 2;
}
return true;
}
static void
ReadAndValidateExceptionTimeAnnotations(FILE*& aFd,
AnnotationTable& aAnnotations)
{
char line[0x1000];
while (fgets(line, sizeof(line), aFd)) {
char* data = strchr(line, '=');
if (!data) {
// bad data? Abort!
break;
}
// Move past the '='
*data = 0;
++data;
size_t dataLen = strlen(data);
// Chop off any trailing newline
if (dataLen > 0 && data[dataLen - 1] == '\n') {
data[dataLen - 1] = 0;
--dataLen;
}
// There should not be any newlines in the key
if (strchr(line, '\n')) {
break;
}
// Data should have been escaped by the child
if (!IsDataEscaped(data)) {
break;
}
// Looks good, save the (line,data) pair
aAnnotations.Put(nsDependentCString(line),
nsDependentCString(data, dataLen));
}
}
/**
* NOTE: One side effect of this function is that it deletes the
* GeckoChildCrash<pid>.extra file if it exists, once processed.
*/
static bool
WriteExtraForMinidump(nsIFile* minidump,
uint32_t pid,
const Blacklist& blacklist,
nsIFile** extraFile)
{
nsCOMPtr<nsIFile> extra;
if (!GetExtraFileForMinidump(minidump, getter_AddRefs(extra)))
if (!GetExtraFileForMinidump(minidump, getter_AddRefs(extra))) {
return false;
}
if (!WriteExtraData(extra, *crashReporterAPIData_Hash,
blacklist,
true /*write crash time*/,
true /*truncate*/))
true /*truncate*/)) {
return false;
}
*extraFile = nullptr;
extra.swap(*extraFile);
nsCOMPtr<nsIFile> exceptionTimeExtra;
FILE* fd;
if (pid && GetExtraFileForChildPid(minidump, pid,
getter_AddRefs(exceptionTimeExtra)) &&
NS_SUCCEEDED(exceptionTimeExtra->OpenANSIFileDesc("r", &fd))) {
AnnotationTable exceptionTimeAnnotations;
ReadAndValidateExceptionTimeAnnotations(fd, exceptionTimeAnnotations);
fclose(fd);
if (!AppendExtraData(extra, exceptionTimeAnnotations)) {
return false;
}
}
if (exceptionTimeExtra) {
exceptionTimeExtra->Remove(false);
}
extra.forget(extraFile);
return true;
}
@ -2775,7 +3111,14 @@ OnChildProcessDumpRequested(void* aContext,
#endif
getter_AddRefs(minidump));
if (!WriteExtraForMinidump(minidump,
uint32_t pid =
#ifdef XP_MACOSX
aClientInfo.pid();
#else
aClientInfo->pid();
#endif
if (!WriteExtraForMinidump(minidump, pid,
Blacklist(kSubprocessBlacklist,
ArrayLength(kSubprocessBlacklist)),
getter_AddRefs(extraFile)))
@ -2785,12 +3128,6 @@ OnChildProcessDumpRequested(void* aContext,
MoveToPending(minidump, extraFile);
{
uint32_t pid =
#ifdef XP_MACOSX
aClientInfo.pid();
#else
aClientInfo->pid();
#endif
#ifdef MOZ_CRASHREPORTER_INJECTOR
bool runCallback;
@ -2818,13 +3155,6 @@ OOPInitialized()
return pidToMinidump != nullptr;
}
#ifdef XP_MACOSX
static bool ChildFilter(void *context) {
mozilla::IOInterposer::Disable();
return true;
}
#endif
void
OOPInit()
{
@ -2851,6 +3181,14 @@ OOPInit()
MOZ_ASSERT(gExceptionHandler != nullptr,
"attempt to initialize OOP crash reporter before in-process crashreporter!");
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
nsCOMPtr<nsIFile> tmpDir;
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
if (NS_SUCCEEDED(rv)) {
contentProcessTmpDir = CreatePathFromFile(tmpDir);
}
#endif
#if defined(XP_WIN)
childCrashNotifyPipe =
PR_smprintf("\\\\.\\pipe\\gecko-crash-server-pipe.%i",
@ -2889,7 +3227,7 @@ OOPInit()
crashServer = new CrashGenerationServer(
childCrashNotifyPipe,
ChildFilter,
nullptr,
nullptr,
OnChildProcessDumpRequested, nullptr,
nullptr, nullptr,
@ -3097,16 +3435,16 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
gExceptionHandler = new google_breakpad::
ExceptionHandler(L"",
FPEFilter,
ChildFPEFilter,
nullptr, // no minidump callback
nullptr, // no callback context
google_breakpad::ExceptionHandler::HANDLER_ALL,
MiniDumpNormal,
NS_ConvertASCIItoUTF16(crashPipe).get(),
nullptr);
#ifdef XP_WIN
gExceptionHandler->set_handle_debug_exceptions(true);
#endif
mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
@ -3139,15 +3477,12 @@ SetRemoteExceptionHandler()
{
MOZ_ASSERT(!gExceptionHandler, "crash client already init'd");
#ifndef XP_LINUX
xpstring path = "";
#else
// MinidumpDescriptor requires a non-empty path.
google_breakpad::MinidumpDescriptor path(".");
#endif
gExceptionHandler = new google_breakpad::
ExceptionHandler(path,
nullptr, // no filter callback
ChildFilter,
nullptr, // no minidump callback
nullptr, // no callback context
true, // install signal handlers
@ -3160,6 +3495,8 @@ SetRemoteExceptionHandler()
delete gDelayedAnnotations;
}
mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}
@ -3178,12 +3515,14 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
gExceptionHandler = new google_breakpad::
ExceptionHandler("",
Filter,
ChildFilter,
nullptr, // no minidump callback
nullptr, // no callback context
true, // install signal handlers
crashPipe.BeginReading());
mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}
@ -3297,7 +3636,7 @@ PairedDumpCallbackExtra(
nsCOMPtr<nsIFile>& minidump = *static_cast< nsCOMPtr<nsIFile>* >(context);
nsCOMPtr<nsIFile> extra;
return WriteExtraForMinidump(minidump, Blacklist(), getter_AddRefs(extra));
return WriteExtraForMinidump(minidump, 0, Blacklist(), getter_AddRefs(extra));
}
ThreadId

View File

@ -7,12 +7,12 @@ function run_test()
return;
}
// Try crashing with a pure virtual call
// Try crashing with a runtime abort
do_content_crash(function() {
crashType = CrashTestUtils.CRASH_RUNTIMEABORT;
crashReporter.annotateCrashReport("TestKey", "TestValue");
crashReporter.appendAppNotesToCrashReport("!!!foo!!!");
},
},
function(mdump, extra) {
do_check_eq(extra.TestKey, "TestValue");
do_check_true('StartupTime' in extra);

View File

@ -0,0 +1,17 @@
load("../unit/head_crashreporter.js");
function run_test()
{
if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
dump("INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n");
return;
}
// Try crashing with an OOM
do_content_crash(function() {
crashType = CrashTestUtils.CRASH_OOM;
},
function(mdump, extra) {
do_check_true('OOMAllocationSize' in extra);
});
}

View File

@ -4,3 +4,4 @@ tail =
skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_content_annotation.js]
[test_content_exception_time_annotation.js]

View File

@ -604,37 +604,15 @@ CanShowProfileManager()
return true;
}
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
static const char*
SandboxTempDirParent()
{
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
}
#endif
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
static const char*
SandboxTempDirParent()
{
return NS_OS_TEMP_DIR;
}
#endif
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
static already_AddRefed<nsIFile>
GetAndCleanTempDir(const nsAString& aTempDirSuffix)
GetAndCleanTempDir()
{
// Get the directory within which we'll place the
// sandbox-writable temp directory
nsCOMPtr<nsIFile> tempDir;
nsresult rv = NS_GetSpecialDirectory(SandboxTempDirParent(),
getter_AddRefs(tempDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
// Append our profile specific temp name.
rv = tempDir->Append(NS_LITERAL_STRING("Temp-") + aTempDirSuffix);
nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
getter_AddRefs(tempDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
@ -715,7 +693,7 @@ SetUpSandboxEnvironment()
}
// Get (and clean up if still there) the sandbox-writable temp directory.
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir(tempDirSuffix);
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir();
if (!tempDir) {
NS_WARNING("Failed to get or clean sandboxed temp directory.");
return;
@ -737,16 +715,9 @@ CleanUpSandboxEnvironment()
}
#endif
// Get temp directory suffix pref.
nsAdoptingString tempDirSuffix =
Preferences::GetString("security.sandbox.content.tempDirSuffix");
if (tempDirSuffix.IsEmpty()) {
return;
}
// Get and remove the sandbox-writable temp directory.
// This function already warns if the deletion fails.
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir(tempDirSuffix);
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir();
}
#endif

View File

@ -397,6 +397,14 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
bool unused;
rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file));
}
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
else if (!strcmp(aProperty, NS_APP_CONTENT_PROCESS_TEMP_DIR)) {
if (!mContentTempDir && NS_FAILED((rv = LoadContentProcessTempDir()))) {
return rv;
}
rv = mContentTempDir->Clone(getter_AddRefs(file));
}
#endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
// We need to allow component, xpt, and chrome registration to
// occur prior to the profile-after-change notification.
@ -620,6 +628,50 @@ LoadExtensionDirectories(nsINIParser &parser,
while (true);
}
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
static const char*
GetContentProcessTempBaseDirKey()
{
#if defined(XP_WIN)
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
#else
return NS_OS_TEMP_DIR;
#endif
}
nsresult
nsXREDirProvider::LoadContentProcessTempDir()
{
nsCOMPtr<nsIFile> localFile;
nsresult rv = NS_GetSpecialDirectory(GetContentProcessTempBaseDirKey(),
getter_AddRefs(localFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoString tempDirSuffix;
rv = Preferences::GetString("security.sandbox.content.tempDirSuffix",
&tempDirSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (tempDirSuffix.IsEmpty()) {
return NS_ERROR_NOT_AVAILABLE;
}
rv = localFile->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
localFile.swap(mContentTempDir);
return NS_OK;
}
#endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
void
nsXREDirProvider::LoadExtensionBundleDirectories()
{
@ -869,6 +921,7 @@ nsXREDirProvider::DoStartup()
static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
// Init the Extension Manager
nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
if (em) {

View File

@ -121,6 +121,11 @@ protected:
// delimiters.
static inline nsresult AppendProfileString(nsIFile* aFile, const char* aPath);
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
// Load the temp directory for sandboxed content processes
nsresult LoadContentProcessTempDir();
#endif
// Calculate and register extension and theme bundle directories.
void LoadExtensionBundleDirectories();
@ -141,6 +146,9 @@ protected:
nsCOMPtr<nsIFile> mProfileDir;
nsCOMPtr<nsIFile> mProfileLocalDir;
bool mProfileNotified;
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
nsCOMPtr<nsIFile> mContentTempDir;
#endif
nsCOMArray<nsIFile> mAppBundleDirectories;
nsCOMArray<nsIFile> mExtensionDirectories;
nsCOMArray<nsIFile> mThemeDirectories;

View File

@ -83,4 +83,9 @@
#define NS_APP_INDEXEDDB_PARENT_DIR "indexedDBPDir"
#define NS_APP_PERMISSION_PARENT_DIR "permissionDBPDir"
#endif
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
#define NS_APP_CONTENT_PROCESS_TEMP_DIR "ContentTmpD"
#endif // (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
#endif // nsAppDirectoryServiceDefs_h___