зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1407693 - Part 2 - when a child process crashes, write extra annotation data to a pre-opened file descriptor instead of creating a new file; r=gsvelto,rbarker
This removes the need for the content process to have permissions to create new files on macOS, allowing more aggressive sandboxing. MozReview-Commit-ID: 8agL5jwxDSL --HG-- extra : rebase_source : 17ebcef3e9d24f3d4e7515e3fae95e65cef76a79
This commit is contained in:
Родитель
0d04153faf
Коммит
de20b74dc4
|
@ -63,6 +63,7 @@
|
|||
#include "nsHashKeys.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
|
||||
#include "private/pprio.h"
|
||||
|
||||
using mozilla::MonitorAutoLock;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
|
@ -122,6 +123,16 @@ GeckoChildProcessHost::~GeckoChildProcessHost()
|
|||
if (mChildTask != MACH_PORT_NULL)
|
||||
mach_port_deallocate(mach_task_self(), mChildTask);
|
||||
#endif
|
||||
|
||||
if (mChildProcessHandle != 0) {
|
||||
#if defined(XP_WIN)
|
||||
CrashReporter::DeregisterChildCrashAnnotationFileDescriptor(
|
||||
base::GetProcId(mChildProcessHandle));
|
||||
#else
|
||||
CrashReporter::DeregisterChildCrashAnnotationFileDescriptor(
|
||||
mChildProcessHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
|
@ -621,6 +632,12 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
const char* const childProcessType =
|
||||
XRE_ChildProcessTypeToString(mProcessType);
|
||||
|
||||
PRFileDesc* crashAnnotationReadPipe;
|
||||
PRFileDesc* crashAnnotationWritePipe;
|
||||
if (PR_CreatePipe(&crashAnnotationReadPipe, &crashAnnotationWritePipe) != PR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
#if defined(OS_POSIX)
|
||||
// For POSIX, we have to be extremely anal about *not* using
|
||||
|
@ -769,6 +786,10 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
#endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
}
|
||||
|
||||
int fd = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
|
||||
mLaunchOptions->fds_to_remap.push_back(
|
||||
std::make_pair(fd, CrashReporter::GetAnnotationTimeCrashFd()));
|
||||
|
||||
# ifdef MOZ_WIDGET_COCOA
|
||||
// Add a mach port to the command line so the child can communicate its
|
||||
// 'task_t' back to the parent.
|
||||
|
@ -1007,6 +1028,14 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
cmdLine.AppendLooseValue(
|
||||
UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
|
||||
|
||||
PROsfd h = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
|
||||
# if defined(MOZ_SANDBOX)
|
||||
mSandboxBroker.AddHandleToShare(reinterpret_cast<HANDLE>(h));
|
||||
# endif // defined(MOZ_SANDBOX)
|
||||
mLaunchOptions->handles_to_inherit.push_back(reinterpret_cast<HANDLE>(h));
|
||||
std::string hStr = std::to_string(h);
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(hStr));
|
||||
|
||||
// Process type
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
|
||||
|
@ -1069,6 +1098,15 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
) {
|
||||
MOZ_CRASH("cannot open handle to child process");
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
CrashReporter::RegisterChildCrashAnnotationFileDescriptor(
|
||||
base::GetProcId(process), crashAnnotationReadPipe);
|
||||
#else
|
||||
CrashReporter::RegisterChildCrashAnnotationFileDescriptor(process,
|
||||
crashAnnotationReadPipe);
|
||||
#endif
|
||||
PR_Close(crashAnnotationWritePipe);
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mProcessState = PROCESS_CREATED;
|
||||
lock.Notify();
|
||||
|
@ -1140,7 +1178,7 @@ GeckoChildProcessHost::LaunchAndroidService(const char* type,
|
|||
const base::file_handle_mapping_vector& fds_to_remap,
|
||||
ProcessHandle* process_handle)
|
||||
{
|
||||
MOZ_ASSERT((fds_to_remap.size() > 0) && (fds_to_remap.size() <= 2));
|
||||
MOZ_ASSERT((fds_to_remap.size() > 0) && (fds_to_remap.size() <= 3));
|
||||
JNIEnv* const env = mozilla::jni::GetEnvForThread();
|
||||
MOZ_ASSERT(env);
|
||||
|
||||
|
@ -1154,7 +1192,8 @@ GeckoChildProcessHost::LaunchAndroidService(const char* type,
|
|||
it++;
|
||||
// If the Crash Reporter is disabled, there will not be a second file descriptor.
|
||||
int32_t crashFd = (it != fds_to_remap.end()) ? it->first : -1;
|
||||
int32_t handle = java::GeckoProcessManager::Start(type, jargs, crashFd, ipcFd);
|
||||
int32_t crashAnnotationFd = (it != fds_to_remap.end()) ? it->first : -1;
|
||||
int32_t handle = java::GeckoProcessManager::Start(type, jargs, crashFd, ipcFd, crashAnnotationFd);
|
||||
|
||||
if (process_handle) {
|
||||
*process_handle = handle;
|
||||
|
|
|
@ -10,5 +10,5 @@ import android.os.ParcelFileDescriptor;
|
|||
|
||||
interface IChildProcess {
|
||||
int getPid();
|
||||
boolean start(in IProcessManager procMan, in String[] args, in ParcelFileDescriptor crashReporterPfd, in ParcelFileDescriptor ipcPfd);
|
||||
boolean start(in IProcessManager procMan, in String[] args, in ParcelFileDescriptor crashReporterPfd, in ParcelFileDescriptor ipcPfd, in ParcelFileDescriptor crashAnnotationPfd);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ public class GeckoThread extends Thread {
|
|||
// Child process parameters
|
||||
private int mCrashFileDescriptor = -1;
|
||||
private int mIPCFileDescriptor = -1;
|
||||
private int mCrashAnnotationFileDescriptor = -1;
|
||||
|
||||
GeckoThread() {
|
||||
setName("Gecko");
|
||||
|
@ -139,7 +140,8 @@ public class GeckoThread extends Thread {
|
|||
|
||||
private synchronized boolean init(final GeckoProfile profile, final String[] args,
|
||||
final String extraArgs, final int flags,
|
||||
final int crashFd, final int ipcFd) {
|
||||
final int crashFd, final int ipcFd,
|
||||
final int crashAnnotationFd) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
uiThreadId = android.os.Process.myTid();
|
||||
|
||||
|
@ -153,6 +155,7 @@ public class GeckoThread extends Thread {
|
|||
mFlags = flags;
|
||||
mCrashFileDescriptor = crashFd;
|
||||
mIPCFileDescriptor = ipcFd;
|
||||
mCrashAnnotationFileDescriptor = crashAnnotationFd;
|
||||
|
||||
mInitialized = true;
|
||||
notifyAll();
|
||||
|
@ -162,13 +165,15 @@ public class GeckoThread extends Thread {
|
|||
public static boolean initMainProcess(final GeckoProfile profile, final String extraArgs,
|
||||
final int flags) {
|
||||
return INSTANCE.init(profile, /* args */ null, extraArgs, flags,
|
||||
/* crashFd */ -1, /* ipcFd */ -1);
|
||||
/* crashFd */ -1, /* ipcFd */ -1,
|
||||
/* crashAnnotationFd */ -1);
|
||||
}
|
||||
|
||||
public static boolean initChildProcess(final String[] args, final int crashFd,
|
||||
final int ipcFd) {
|
||||
final int ipcFd,
|
||||
final int crashAnnotationFd) {
|
||||
return INSTANCE.init(/* profile */ null, args, /* extraArgs */ null,
|
||||
/* flags */ 0, crashFd, ipcFd);
|
||||
/* flags */ 0, crashFd, ipcFd, crashAnnotationFd);
|
||||
}
|
||||
|
||||
private static boolean canUseProfile(final Context context, final GeckoProfile profile,
|
||||
|
@ -404,7 +409,7 @@ public class GeckoThread extends Thread {
|
|||
}
|
||||
|
||||
// And go.
|
||||
GeckoLoader.nativeRun(args, mCrashFileDescriptor, mIPCFileDescriptor);
|
||||
GeckoLoader.nativeRun(args, mCrashFileDescriptor, mIPCFileDescriptor, mCrashAnnotationFileDescriptor);
|
||||
|
||||
// And... we're done.
|
||||
final boolean restarting = isState(State.RESTARTING);
|
||||
|
|
|
@ -493,7 +493,7 @@ public final class GeckoLoader {
|
|||
private static native void putenv(String map);
|
||||
|
||||
// These methods are implemented in mozglue/android/APKOpen.cpp
|
||||
public static native void nativeRun(String[] args, int crashFd, int ipcFd);
|
||||
public static native void nativeRun(String[] args, int crashFd, int ipcFd, int crashAnnotationFd);
|
||||
private static native void loadGeckoLibsNative(String apkName);
|
||||
private static native void loadSQLiteLibsNative(String apkName);
|
||||
private static native void loadNSSLibsNative(String apkName);
|
||||
|
|
|
@ -168,12 +168,14 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
|
||||
@WrapForJNI
|
||||
private static int start(final String type, final String[] args,
|
||||
final int crashFd, final int ipcFd) {
|
||||
return INSTANCE.start(type, args, crashFd, ipcFd, /* retry */ false);
|
||||
final int crashFd, final int ipcFd,
|
||||
final int crashAnnotationFd) {
|
||||
return INSTANCE.start(type, args, crashFd, ipcFd, crashAnnotationFd, /* retry */ false);
|
||||
}
|
||||
|
||||
private int start(final String type, final String[] args, final int crashFd,
|
||||
final int ipcFd, final boolean retry) {
|
||||
final int ipcFd, final int crashAnnotationFd,
|
||||
final boolean retry) {
|
||||
final ChildConnection connection = getConnection(type);
|
||||
final IChildProcess child = connection.bind();
|
||||
if (child == null) {
|
||||
|
@ -182,9 +184,11 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
|
||||
final ParcelFileDescriptor crashPfd;
|
||||
final ParcelFileDescriptor ipcPfd;
|
||||
final ParcelFileDescriptor crashAnnotationPfd;
|
||||
try {
|
||||
crashPfd = (crashFd >= 0) ? ParcelFileDescriptor.fromFd(crashFd) : null;
|
||||
ipcPfd = ParcelFileDescriptor.fromFd(ipcFd);
|
||||
crashAnnotationPfd = (crashAnnotationFd >= 0) ? ParcelFileDescriptor.fromFd(crashAnnotationFd) : null;
|
||||
} catch (final IOException e) {
|
||||
Log.e(LOGTAG, "Cannot create fd for " + type, e);
|
||||
return 0;
|
||||
|
@ -192,7 +196,7 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
|
||||
boolean started = false;
|
||||
try {
|
||||
started = child.start(this, args, crashPfd, ipcPfd);
|
||||
started = child.start(this, args, crashPfd, ipcPfd, crashAnnotationPfd);
|
||||
} catch (final RemoteException e) {
|
||||
}
|
||||
|
||||
|
@ -203,7 +207,7 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
}
|
||||
Log.w(LOGTAG, "Attempting to kill running child " + type);
|
||||
connection.unbind();
|
||||
return start(type, args, crashFd, ipcFd, /* retry */ true);
|
||||
return start(type, args, crashFd, ipcFd, crashAnnotationFd, /* retry */ true);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -62,7 +62,8 @@ public class GeckoServiceChildProcess extends Service {
|
|||
public boolean start(final IProcessManager procMan,
|
||||
final String[] args,
|
||||
final ParcelFileDescriptor crashReporterPfd,
|
||||
final ParcelFileDescriptor ipcPfd) {
|
||||
final ParcelFileDescriptor ipcPfd,
|
||||
final ParcelFileDescriptor crashAnnotationPfd) {
|
||||
synchronized (GeckoServiceChildProcess.class) {
|
||||
if (sProcessManager != null) {
|
||||
Log.e(LOGTAG, "Child process already started");
|
||||
|
@ -74,11 +75,12 @@ public class GeckoServiceChildProcess extends Service {
|
|||
final int crashReporterFd = crashReporterPfd != null ?
|
||||
crashReporterPfd.detachFd() : -1;
|
||||
final int ipcFd = ipcPfd != null ? ipcPfd.detachFd() : -1;
|
||||
final int crashAnnotationFd = crashAnnotationPfd != null ? crashAnnotationPfd.detachFd() : -1;
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (GeckoThread.initChildProcess(args, crashReporterFd, ipcFd)) {
|
||||
if (GeckoThread.initChildProcess(args, crashReporterFd, ipcFd, crashAnnotationFd)) {
|
||||
GeckoThread.launch();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ FreeArgv(char** argv, int argc)
|
|||
}
|
||||
|
||||
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
||||
Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd)
|
||||
Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd, int crashAnnotationFd)
|
||||
{
|
||||
int argc = 0;
|
||||
char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
|
||||
|
@ -423,7 +423,7 @@ Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jo
|
|||
gBootstrap->GeckoStart(jenv, argv, argc, sAppData);
|
||||
ElfLoader::Singleton.ExpectShutdown(true);
|
||||
} else {
|
||||
gBootstrap->XRE_SetAndroidChildFds(jenv, crashFd, ipcFd);
|
||||
gBootstrap->XRE_SetAndroidChildFds(jenv, crashFd, ipcFd, crashAnnotationFd);
|
||||
gBootstrap->XRE_SetProcessType(argv[argc - 1]);
|
||||
|
||||
XREChildData childData;
|
||||
|
|
|
@ -141,6 +141,24 @@ SetRestartArgs(int argc, char** argv)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#if !defined(XP_WIN)
|
||||
int
|
||||
GetAnnotationTimeCrashFd()
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess, PRFileDesc* aFd)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef XP_WIN32
|
||||
nsresult
|
||||
WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo)
|
||||
|
@ -298,16 +316,10 @@ GetLastRunCrashID(nsAString& id)
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
void
|
||||
InitChildProcessTmpDir(nsIFile* aDirOverride)
|
||||
{
|
||||
}
|
||||
#endif // defined(XP_WIN) || defined(XP_MACOSX)
|
||||
|
||||
#if defined(XP_WIN)
|
||||
bool
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe,
|
||||
uintptr_t aCrashTimeAnnotationFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -391,6 +403,11 @@ SetNotificationPipeForChild(int childCrashFd)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
SetCrashAnnotationPipeForChild(int childCrashAnnotationFd)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AddLibraryMapping(const char* library_name,
|
||||
uintptr_t start_address,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsXULAppAPI.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "ThreadAnnotation.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
#if defined(XP_WIN32)
|
||||
#ifdef WIN32_LEAN_AND_MEAN
|
||||
|
@ -242,6 +243,7 @@ static bool sIncludeContextHeap = false;
|
|||
|
||||
// OOP crash reporting
|
||||
static CrashGenerationServer* crashServer; // chrome process has this
|
||||
static std::map<ProcessId, PRFileDesc*> processToCrashFd;
|
||||
|
||||
static std::terminate_handler oldTerminateHandler = nullptr;
|
||||
|
||||
|
@ -269,6 +271,10 @@ static int gMagicChildCrashReportFd =
|
|||
;
|
||||
# endif
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
static int gChildCrashAnnotationReportFd = -1;
|
||||
#endif
|
||||
|
||||
// |dumpMapLock| must protect all access to |pidToMinidump|.
|
||||
static Mutex* dumpMapLock;
|
||||
struct ChildProcessData : public nsUint32HashKey
|
||||
|
@ -579,6 +585,8 @@ public:
|
|||
nullptr);
|
||||
}
|
||||
|
||||
void OpenHandle(HANDLE aHandle) { mHandle = aHandle; }
|
||||
|
||||
bool Valid() {
|
||||
return mHandle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
@ -625,6 +633,8 @@ public:
|
|||
mFD = sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
}
|
||||
|
||||
void OpenHandle(int aFd) { mFD = aFd; }
|
||||
|
||||
bool Valid() {
|
||||
return mFD != -1;
|
||||
}
|
||||
|
@ -1261,45 +1271,18 @@ BuildTempPath(PathStringT& aResult)
|
|||
}
|
||||
|
||||
static void
|
||||
PrepareChildExceptionTimeAnnotations()
|
||||
PrepareChildExceptionTimeAnnotations(void* context)
|
||||
{
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
static XP_CHAR tempPath[XP_PATH_MAX] = {0};
|
||||
|
||||
// Get the temp path
|
||||
size_t charsAvailable = XP_PATH_MAX;
|
||||
XP_CHAR* p = tempPath;
|
||||
#if (defined(XP_MACOSX) || defined(XP_WIN))
|
||||
if (!childProcessTmpDir || childProcessTmpDir->empty()) {
|
||||
return;
|
||||
}
|
||||
p = Concat(p, childProcessTmpDir->c_str(), &charsAvailable);
|
||||
// Ensure that this path ends with a path separator
|
||||
if (p > tempPath && *(p - 1) != XP_PATH_SEPARATOR_CHAR) {
|
||||
p = Concat(p, XP_PATH_SEPARATOR, &charsAvailable);
|
||||
}
|
||||
FileHandle f;
|
||||
#ifdef XP_WIN
|
||||
f = static_cast<HANDLE>(context);
|
||||
#else
|
||||
size_t tempPathLen = BuildTempPath(tempPath);
|
||||
if (!tempPathLen) {
|
||||
return;
|
||||
}
|
||||
p += tempPathLen;
|
||||
charsAvailable -= tempPathLen;
|
||||
f = GetAnnotationTimeCrashFd();
|
||||
#endif
|
||||
|
||||
// Generate and append the file name
|
||||
p = Concat(p, childCrashAnnotationBaseName, &charsAvailable);
|
||||
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, &charsAvailable);
|
||||
|
||||
// Now open the file...
|
||||
PlatformWriter apiData;
|
||||
OpenAPIData(apiData, tempPath);
|
||||
apiData.OpenHandle(f);
|
||||
|
||||
// ...and write out any annotations. These must be escaped if necessary
|
||||
// (but don't call EscapeAnnotation here, because it touches the heap).
|
||||
|
@ -1395,7 +1378,7 @@ ChildFPEFilter(void* context, EXCEPTION_POINTERS* exinfo,
|
|||
{
|
||||
bool result = FPEFilter(context, exinfo, assertion);
|
||||
if (result) {
|
||||
PrepareChildExceptionTimeAnnotations();
|
||||
PrepareChildExceptionTimeAnnotations(context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1461,7 +1444,7 @@ ChildFilter(void* context)
|
|||
{
|
||||
bool result = Filter(context);
|
||||
if (result) {
|
||||
PrepareChildExceptionTimeAnnotations();
|
||||
PrepareChildExceptionTimeAnnotations(context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -3056,50 +3039,6 @@ AppendExtraData(nsIFile* extraFile, const AnnotationTable& data)
|
|||
return WriteExtraData(extraFile, data, Blacklist());
|
||||
}
|
||||
|
||||
static bool
|
||||
GetExtraFileForChildPid(uint32_t aPid, nsIFile** aExtraFile)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
nsCOMPtr<nsIFile> extraFile;
|
||||
nsresult rv;
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
if (!childProcessTmpDir) {
|
||||
return false;
|
||||
}
|
||||
CreateFileFromPath(*childProcessTmpDir, getter_AddRefs(extraFile));
|
||||
if (!extraFile) {
|
||||
return false;
|
||||
}
|
||||
#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
|
||||
|
||||
rv = extraFile->Append(leafName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
extraFile.forget(aExtraFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsDataEscaped(char* aData)
|
||||
{
|
||||
|
@ -3174,19 +3113,27 @@ WriteExtraForMinidump(nsIFile* minidump,
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> exceptionTimeExtra;
|
||||
FILE* fd;
|
||||
if (pid && GetExtraFileForChildPid(pid, getter_AddRefs(exceptionTimeExtra)) &&
|
||||
NS_SUCCEEDED(exceptionTimeExtra->OpenANSIFileDesc("r", &fd))) {
|
||||
AnnotationTable exceptionTimeAnnotations;
|
||||
ReadAndValidateExceptionTimeAnnotations(fd, exceptionTimeAnnotations);
|
||||
fclose(fd);
|
||||
if (!AppendExtraData(extra, exceptionTimeAnnotations)) {
|
||||
if (pid && processToCrashFd.count(pid)) {
|
||||
PRFileDesc* prFd = processToCrashFd[pid];
|
||||
processToCrashFd.erase(pid);
|
||||
FILE* fd;
|
||||
#if defined(XP_WIN)
|
||||
int nativeFd = _open_osfhandle(PR_FileDesc2NativeHandle(prFd), 0);
|
||||
if (nativeFd == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (exceptionTimeExtra) {
|
||||
exceptionTimeExtra->Remove(false);
|
||||
fd = fdopen(nativeFd, "r");
|
||||
#else
|
||||
fd = fdopen(PR_FileDesc2NativeHandle(prFd), "r");
|
||||
#endif
|
||||
if (fd) {
|
||||
AnnotationTable exceptionTimeAnnotations;
|
||||
ReadAndValidateExceptionTimeAnnotations(fd, exceptionTimeAnnotations);
|
||||
PR_Close(prFd);
|
||||
if (!AppendExtraData(extra, exceptionTimeAnnotations)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extra.forget(extraFile);
|
||||
|
@ -3538,30 +3485,39 @@ UnregisterInjectorCallback(DWORD processID)
|
|||
|
||||
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
void
|
||||
InitChildProcessTmpDir(nsIFile* aDirOverride)
|
||||
#if !defined(XP_WIN)
|
||||
int
|
||||
GetAnnotationTimeCrashFd()
|
||||
{
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
if (aDirOverride) {
|
||||
childProcessTmpDir = CreatePathFromFile(aDirOverride);
|
||||
return;
|
||||
}
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
return gChildCrashAnnotationReportFd;
|
||||
#else
|
||||
return 7;
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
}
|
||||
#endif
|
||||
|
||||
// When retrieved by the child process, this will always resolve to the
|
||||
// correct directory regardless of sandbox level.
|
||||
nsCOMPtr<nsIFile> tmpDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
childProcessTmpDir = CreatePathFromFile(tmpDir);
|
||||
void
|
||||
RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess, PRFileDesc* aFd)
|
||||
{
|
||||
processToCrashFd[aProcess] = aFd;
|
||||
}
|
||||
|
||||
void
|
||||
DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess)
|
||||
{
|
||||
auto it = processToCrashFd.find(aProcess);
|
||||
if (it != processToCrashFd.end()) {
|
||||
PR_Close(it->second);
|
||||
processToCrashFd.erase(it);
|
||||
}
|
||||
}
|
||||
#endif // defined(XP_WIN) || defined(XP_MACOSX)
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Child-side API
|
||||
bool
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe,
|
||||
uintptr_t aCrashTimeAnnotationFile)
|
||||
{
|
||||
// crash reporting is disabled
|
||||
if (crashPipe.Equals(kNullNotifyPipe))
|
||||
|
@ -3569,15 +3525,15 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
|
|||
|
||||
MOZ_ASSERT(!gExceptionHandler, "crash client already init'd");
|
||||
|
||||
gExceptionHandler = new google_breakpad::
|
||||
ExceptionHandler(L"",
|
||||
ChildFPEFilter,
|
||||
nullptr, // no minidump callback
|
||||
nullptr, // no callback context
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
GetMinidumpType(),
|
||||
NS_ConvertASCIItoUTF16(crashPipe).get(),
|
||||
nullptr);
|
||||
gExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
L"",
|
||||
ChildFPEFilter,
|
||||
nullptr, // no minidump callback
|
||||
reinterpret_cast<void*>(aCrashTimeAnnotationFile),
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
GetMinidumpType(),
|
||||
NS_ConvertASCIItoUTF16(crashPipe).get(),
|
||||
nullptr);
|
||||
gExceptionHandler->set_handle_debug_exceptions(true);
|
||||
RunAndCleanUpDelayedNotes();
|
||||
|
||||
|
@ -4081,6 +4037,11 @@ void SetNotificationPipeForChild(int childCrashFd)
|
|||
gMagicChildCrashReportFd = childCrashFd;
|
||||
}
|
||||
|
||||
void SetCrashAnnotationPipeForChild(int childCrashAnnotationFd)
|
||||
{
|
||||
gChildCrashAnnotationReportFd = childCrashAnnotationFd;
|
||||
}
|
||||
|
||||
void AddLibraryMapping(const char* library_name,
|
||||
uintptr_t start_address,
|
||||
size_t mapping_length,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdint.h>
|
||||
#include "nsError.h"
|
||||
#include "nsString.h"
|
||||
#include "prio.h"
|
||||
|
||||
#if defined(XP_WIN32)
|
||||
#ifdef WIN32_LEAN_AND_MEAN
|
||||
|
@ -176,15 +177,30 @@ bool TakeMinidumpForChild(uint32_t childPid,
|
|||
|
||||
#if defined(XP_WIN)
|
||||
typedef HANDLE ProcessHandle;
|
||||
typedef DWORD ProcessId;
|
||||
typedef DWORD ThreadId;
|
||||
typedef HANDLE FileHandle;
|
||||
#elif defined(XP_MACOSX)
|
||||
typedef task_t ProcessHandle;
|
||||
typedef pid_t ProcessId;
|
||||
typedef mach_port_t ThreadId;
|
||||
typedef int FileHandle;
|
||||
#else
|
||||
typedef int ProcessHandle;
|
||||
typedef pid_t ProcessId;
|
||||
typedef int ThreadId;
|
||||
typedef int FileHandle;
|
||||
#endif
|
||||
|
||||
#if !defined(XP_WIN)
|
||||
int
|
||||
GetAnnotationTimeCrashFd();
|
||||
#endif
|
||||
void
|
||||
RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess, PRFileDesc* aFd);
|
||||
void
|
||||
DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess);
|
||||
|
||||
// Return the current thread's ID.
|
||||
//
|
||||
// XXX: this is a somewhat out-of-place interface to expose through
|
||||
|
@ -264,8 +280,13 @@ void UnregisterInjectorCallback(DWORD processID);
|
|||
#endif
|
||||
|
||||
// Child-side API
|
||||
#if defined(XP_WIN32)
|
||||
bool
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe,
|
||||
uintptr_t aCrashTimeAnnotationFile);
|
||||
#else
|
||||
bool SetRemoteExceptionHandler(const nsACString& crashPipe);
|
||||
void InitChildProcessTmpDir(nsIFile* aDirOverride = nullptr);
|
||||
#endif
|
||||
|
||||
# else
|
||||
// Parent-side API for children
|
||||
|
@ -291,6 +312,7 @@ bool UnsetRemoteExceptionHandler();
|
|||
// Android creates child process as services so we must explicitly set
|
||||
// the handle for the pipe since it can't get remapped to a default value.
|
||||
void SetNotificationPipeForChild(int childCrashFd);
|
||||
void SetCrashAnnotationPipeForChild(int childCrashAnnotationFd);
|
||||
|
||||
// Android builds use a custom library loader, so /proc/<pid>/maps
|
||||
// will just show anonymous mappings for all the non-system
|
||||
|
|
|
@ -78,8 +78,8 @@ public:
|
|||
::GeckoStart(aEnv, argv, argc, aAppData);
|
||||
}
|
||||
|
||||
virtual void XRE_SetAndroidChildFds(JNIEnv* aEnv, int aCrashFd, int aIPCFd) override {
|
||||
::XRE_SetAndroidChildFds(aEnv, aCrashFd, aIPCFd);
|
||||
virtual void XRE_SetAndroidChildFds(JNIEnv* aEnv, int aCrashFd, int aIPCFd, int aCrashAnnotationFd) override {
|
||||
::XRE_SetAndroidChildFds(aEnv, aCrashFd, aIPCFd, aCrashAnnotationFd);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
#ifdef MOZ_WIDGET_ANDROID
|
||||
virtual void GeckoStart(JNIEnv* aEnv, char** argv, int argc, const StaticXREAppData& aAppData) = 0;
|
||||
|
||||
virtual void XRE_SetAndroidChildFds(JNIEnv* aEnv, int aCrashFd, int aIPCFd) = 0;
|
||||
virtual void XRE_SetAndroidChildFds(JNIEnv* aEnv, int aCrashFd, int aIPCFd, int aCrashAnnotationFd) = 0;
|
||||
#endif
|
||||
|
||||
#ifdef LIBFUZZER
|
||||
|
|
|
@ -243,10 +243,11 @@ GeckoProcessType sChildProcessType = GeckoProcessType_Default;
|
|||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
void
|
||||
XRE_SetAndroidChildFds (JNIEnv* env, int crashFd, int ipcFd)
|
||||
XRE_SetAndroidChildFds (JNIEnv* env, int crashFd, int ipcFd, int crashAnnotationFd)
|
||||
{
|
||||
mozilla::jni::SetGeckoThreadEnv(env);
|
||||
CrashReporter::SetNotificationPipeForChild(crashFd);
|
||||
CrashReporter::SetCrashAnnotationPipeForChild(crashAnnotationFd);
|
||||
IPC::Channel::SetClientChannelFd(ipcFd);
|
||||
}
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
|
@ -282,9 +283,17 @@ XRE_TakeMinidumpForChild(uint32_t aChildPid, nsIFile** aDump,
|
|||
}
|
||||
|
||||
bool
|
||||
XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
|
||||
#if defined(XP_WIN)
|
||||
XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/,
|
||||
uintptr_t aCrashTimeAnnotationFile)
|
||||
#else
|
||||
XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/)
|
||||
#endif
|
||||
{
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
#if defined(XP_WIN)
|
||||
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe),
|
||||
aCrashTimeAnnotationFile);
|
||||
#elif defined(XP_MACOSX)
|
||||
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
|
||||
#else
|
||||
return CrashReporter::SetRemoteExceptionHandler();
|
||||
|
@ -479,13 +488,20 @@ XRE_InitChildProcess(int aArgc,
|
|||
SetupErrorHandling(aArgv[0]);
|
||||
|
||||
if (!CrashReporter::IsDummy()) {
|
||||
#if defined(XP_WIN)
|
||||
if (aArgc < 1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
const char* const crashTimeAnnotationArg = aArgv[--aArgc];
|
||||
uintptr_t crashTimeAnnotationFile =
|
||||
static_cast<uintptr_t>(std::stoul(std::string(crashTimeAnnotationArg)));
|
||||
#endif
|
||||
|
||||
if (aArgc < 1)
|
||||
return NS_ERROR_FAILURE;
|
||||
const char* const crashReporterArg = aArgv[--aArgc];
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
#if defined(XP_MACOSX)
|
||||
// on windows and mac, |crashReporterArg| is the named pipe on which the
|
||||
// server is listening for requests, or "-" if crash reporting is
|
||||
// disabled.
|
||||
|
@ -494,6 +510,13 @@ XRE_InitChildProcess(int aArgc,
|
|||
// Bug 684322 will add better visibility into this condition
|
||||
NS_WARNING("Could not setup crash reporting\n");
|
||||
}
|
||||
#elif defined(XP_WIN)
|
||||
if (0 != strcmp("-", crashReporterArg) &&
|
||||
!XRE_SetRemoteExceptionHandler(crashReporterArg,
|
||||
crashTimeAnnotationFile)) {
|
||||
// Bug 684322 will add better visibility into this condition
|
||||
NS_WARNING("Could not setup crash reporting\n");
|
||||
}
|
||||
#else
|
||||
// on POSIX, |crashReporterArg| is "true" if crash reporting is
|
||||
// enabled, false otherwise
|
||||
|
@ -672,10 +695,6 @@ XRE_InitChildProcess(int aArgc,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
CrashReporter::InitChildProcessTmpDir(crashReportTmpDir);
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Set child processes up such that they will get killed after the
|
||||
// chrome process is killed in cases where the user shuts the system
|
||||
|
|
|
@ -2401,9 +2401,9 @@ constexpr char GeckoProcessManager::GetEditableParent_t::signature[];
|
|||
constexpr char GeckoProcessManager::Start_t::name[];
|
||||
constexpr char GeckoProcessManager::Start_t::signature[];
|
||||
|
||||
auto GeckoProcessManager::Start(mozilla::jni::String::Param a0, mozilla::jni::ObjectArray::Param a1, int32_t a2, int32_t a3) -> int32_t
|
||||
auto GeckoProcessManager::Start(mozilla::jni::String::Param a0, mozilla::jni::ObjectArray::Param a1, int32_t a2, int32_t a3, int32_t a4) -> int32_t
|
||||
{
|
||||
return mozilla::jni::Method<Start_t>::Call(GeckoProcessManager::Context(), nullptr, a0, a1, a2, a3);
|
||||
return mozilla::jni::Method<Start_t>::Call(GeckoProcessManager::Context(), nullptr, a0, a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
const char GeckoServiceChildProcess::name[] =
|
||||
|
|
|
@ -6921,10 +6921,11 @@ public:
|
|||
mozilla::jni::String::Param,
|
||||
mozilla::jni::ObjectArray::Param,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t> Args;
|
||||
static constexpr char name[] = "start";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;[Ljava/lang/String;II)I";
|
||||
"(Ljava/lang/String;[Ljava/lang/String;III)I";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
|
@ -6934,7 +6935,7 @@ public:
|
|||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto Start(mozilla::jni::String::Param, mozilla::jni::ObjectArray::Param, int32_t, int32_t) -> int32_t;
|
||||
static auto Start(mozilla::jni::String::Param, mozilla::jni::ObjectArray::Param, int32_t, int32_t, int32_t) -> int32_t;
|
||||
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
|
|
|
@ -398,7 +398,7 @@ XRE_API(const char*,
|
|||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
XRE_API(void,
|
||||
XRE_SetAndroidChildFds, (JNIEnv* env, int crashFd, int ipcFd))
|
||||
XRE_SetAndroidChildFds, (JNIEnv* env, int crashFd, int ipcFd, int crashAnnotationFd))
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
|
||||
XRE_API(void,
|
||||
|
@ -410,8 +410,16 @@ XRE_API(bool,
|
|||
uint32_t* aSequence))
|
||||
|
||||
// Used in child processes.
|
||||
#if defined(XP_WIN)
|
||||
// Uses uintptr_t, even though it's really a HANDLE, because including
|
||||
// <windows.h> here caused compilation issues.
|
||||
XRE_API(bool,
|
||||
XRE_SetRemoteExceptionHandler,
|
||||
(const char* aPipe, uintptr_t aCrashTimeAnnotationFile))
|
||||
#else
|
||||
XRE_API(bool,
|
||||
XRE_SetRemoteExceptionHandler, (const char* aPipe))
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
|
Загрузка…
Ссылка в новой задаче