Bug 1258317 - Part 1: Annotate the crash report with process information on failure to transfer an IPC transport to another process. r=krizsa, a=ritu
authorCervantes Yu <cyu@mozilla.com>
Sat, 23 Apr 2016 13:04:59 +0200
changeset 324138 5ee8c003df7bb339b39a8145911dc79c291c800f
parent 324137 6bf374e42b5ed6bf8f424ec39354e0868c7d1222
child 324139 b23b92a9f104ffa77c1563991ea75ce8845d7f62
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskrizsa, ritu
bugs1258317
milestone47.0a2
Bug 1258317 - Part 1: Annotate the crash report with process information on failure to transfer an IPC transport to another process. r=krizsa, a=ritu MozReview-Commit-ID: LE2FnrQgzze
ipc/glue/ProtocolUtils.cpp
ipc/glue/ProtocolUtils.h
ipc/glue/Transport_win.cpp
--- 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
 ProtocolErrorBreakpoint(const char* aMsg)
 {
     // Bugs that generate these error messages can be tough to
     // reproduce.  Log always in the hope that someone finds the error
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -329,23 +329,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;