Bug 1258317 - Part 1: Annotate the crash report with process information on failure to transfer an IPC transport to another process. r?gabor
MozReview-Commit-ID: LE2FnrQgzze
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -16,16 +16,21 @@
#include "mozilla/ipc/Transport.h"
#include "mozilla/StaticMutex.h"
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxTarget.h"
#endif
+#if defined(MOZ_CRASHREPORTER) && defined(XP_WIN)
+#include "Aclapi.h"
+#include "Sddl.h"
+#endif
+
using namespace IPC;
using base::GetCurrentProcId;
using base::ProcessHandle;
using base::ProcessId;
namespace mozilla {
namespace ipc {
@@ -295,28 +300,111 @@ bool DuplicateHandle(HANDLE aSourceHandl
return !!::DuplicateHandle(::GetCurrentProcess(), aSourceHandle,
targetProcess, aTargetHandle,
aDesiredAccess, FALSE, aOptions);
}
#endif
#ifdef MOZ_CRASHREPORTER
-void AnnotateSystemError()
+void
+AnnotateSystemError()
{
int64_t error = 0;
#if defined(XP_WIN)
error = ::GetLastError();
#elif defined(OS_POSIX)
error = errno;
#endif
if (error) {
- CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SystemError"),
- nsPrintfCString("%lld", error));
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCSystemError"),
+ nsPrintfCString("%lld", error));
+ }
+}
+
+void
+AnnotateProcessInformation(base::ProcessId aPid)
+{
+#ifdef XP_WIN
+ HANDLE processHandle = OpenProcess(READ_CONTROL|PROCESS_QUERY_INFORMATION, FALSE, aPid);
+ if (!processHandle) {
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCExtraSystemError"),
+ nsPrintfCString("Failed to get information of process %d, error(%d)",
+ aPid,
+ ::GetLastError()));
+ return;
+ }
+
+ DWORD exitCode = 0;
+ if (!::GetExitCodeProcess(processHandle, &exitCode)) {
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCExtraSystemError"),
+ nsPrintfCString("Failed to get exit information of process %d, error(%d)",
+ aPid,
+ ::GetLastError()));
+ return;
+ }
+
+ if (exitCode != STILL_ACTIVE) {
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCExtraSystemError"),
+ nsPrintfCString("Process %d is not alive. Exit code: %d",
+ aPid,
+ exitCode));
+ return;
}
+
+ PSECURITY_DESCRIPTOR secDesc = nullptr;
+ PSID ownerSid = nullptr;
+ DWORD rv = ::GetSecurityInfo(processHandle,
+ SE_KERNEL_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ &ownerSid,
+ nullptr,
+ nullptr,
+ nullptr,
+ &secDesc);
+ if (rv != ERROR_SUCCESS) {
+ // GetSecurityInfo() failed.
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCExtraSystemError"),
+ nsPrintfCString("Failed to get security information of process %d,"
+ " error(%d)",
+ aPid,
+ rv));
+ return;
+ }
+
+ LPTSTR ownerSidStr = nullptr;
+ nsString annotation{};
+ annotation.AppendLiteral("Owner: ");
+ if (::ConvertSidToStringSid(ownerSid, &ownerSidStr)) {
+ annotation.Append(ownerSidStr);
+ }
+ ::LocalFree(ownerSidStr);
+
+ LPTSTR secDescStr = nullptr;
+ annotation.AppendLiteral(", Security Descriptor: ");
+ if (::ConvertSecurityDescriptorToStringSecurityDescriptor(secDesc,
+ SDDL_REVISION_1,
+ DACL_SECURITY_INFORMATION,
+ &secDescStr,
+ nullptr)) {
+ annotation.Append(secDescStr);
+ }
+
+ CrashReporter::AnnotateCrashReport(
+ NS_LITERAL_CSTRING("IPCExtraSystemError"),
+ NS_ConvertUTF16toUTF8(annotation));
+
+ ::LocalFree(secDescStr);
+ ::LocalFree(secDesc);
+#endif
}
#endif
void
LogMessageForProtocol(const char* aTopLevelProtocol, base::ProcessId aOtherPid,
const char* aContextDescription,
const char* aMessageDescription,
MessageDirection aDirection)
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -349,23 +349,25 @@ bool
DuplicateHandle(HANDLE aSourceHandle,
DWORD aTargetProcessId,
HANDLE* aTargetHandle,
DWORD aDesiredAccess,
DWORD aOptions);
#endif
/**
- * Annotate the crash reporter with the error error code from the most recent
- * system call.
+ * Annotate the crash reporter with the error code from the most recent system
+ * call. Returns the system error.
*/
#ifdef MOZ_CRASHREPORTER
void AnnotateSystemError();
+void AnnotateProcessInformation(base::ProcessId aPid);
#else
#define AnnotateSystemError() do { } while (0)
+#define AnnotateProcessInformation(...) do { } while (0)
#endif
/**
* An endpoint represents one end of a partially initialized IPDL channel. To
* set up a new top-level protocol:
*
* Endpoint<PFooParent> parentEp;
* Endpoint<PFooChild> childEp;
--- a/ipc/glue/Transport_win.cpp
+++ b/ipc/glue/Transport_win.cpp
@@ -61,16 +61,17 @@ TransferHandleToProcess(HANDLE source, b
return source;
}
HANDLE handleDup;
DWORD access = 0;
DWORD options = DUPLICATE_SAME_ACCESS;
bool ok = DuplicateHandle(source, pid, &handleDup, access, options);
if (!ok) {
AnnotateSystemError();
+ AnnotateProcessInformation(pid);
}
MOZ_RELEASE_ASSERT(ok);
// Now close our own copy of the handle (we're supposed to be transferring,
// not copying).
CloseHandle(source);
return handleDup;