Bug 945498 - Use breakpad to report seccomp violations as crashes. r=ted, r=kang
authorJed Davis <jld@mozilla.com>
Wed, 05 Feb 2014 13:29:51 -0500
changeset 167166 e2a5bb78e8a533dffada6760fb63b978b3a42bb4
parent 167165 059179513db9384459a071db9fcee8e66722e239
child 167167 08f51dedf516c25845740496e8ba3b98c0499b0e
push id39403
push usercbook@mozilla.com
push dateThu, 06 Feb 2014 12:22:46 +0000
treeherdermozilla-inbound@e3b700ce10fc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, kang
bugs945498, 1114003
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 945498 - Use breakpad to report seccomp violations as crashes. r=ted, r=kang Upstream issue for breakpad patch: https://breakpad.appspot.com/1114003/
ipc/chromium/src/base/process_util_posix.cc
security/sandbox/linux/Sandbox.cpp
toolkit/crashreporter/breakpad-patches/18-bug945498-expose-handle-signal.patch
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
--- a/ipc/chromium/src/base/process_util_posix.cc
+++ b/ipc/chromium/src/base/process_util_posix.cc
@@ -262,16 +262,17 @@ bool DidProcessCrash(bool* child_exited,
     return false;
   }
 
   if (child_exited)
     *child_exited = true;
 
   if (WIFSIGNALED(status)) {
     switch(WTERMSIG(status)) {
+      case SIGSYS:
       case SIGSEGV:
       case SIGILL:
       case SIGABRT:
       case SIGFPE:
         return true;
       default:
         return false;
     }
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -3,21 +3,23 @@
 /* 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/. */
 
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/ptrace.h>
 #include <sys/prctl.h>
+#include <sys/syscall.h>
 #include <signal.h>
 #include <string.h>
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/NullPtr.h"
+#include "nsExceptionHandler.h"
 #if defined(ANDROID)
 #include "android_ucontext.h"
 #include <android/log.h>
 #endif
 #include "seccomp_filter.h"
 
 #include "linux_seccomp.h"
 #ifdef MOZ_LOGGING
@@ -60,40 +62,51 @@ struct sock_fprog seccomp_prog = {
  *
  * @see InstallSyscallReporter() function.
  */
 #ifdef MOZ_CONTENT_SANDBOX_REPORTER
 static void
 Reporter(int nr, siginfo_t *info, void *void_context)
 {
   ucontext_t *ctx = static_cast<ucontext_t*>(void_context);
-  unsigned long syscall, args[6];
+  unsigned long syscall_nr, args[6];
+  pid_t pid = getpid(), tid = syscall(__NR_gettid);
 
   if (nr != SIGSYS) {
     return;
   }
   if (info->si_code != SYS_SECCOMP) {
     return;
   }
   if (!ctx) {
     return;
   }
 
-  syscall = SECCOMP_SYSCALL(ctx);
+  syscall_nr = SECCOMP_SYSCALL(ctx);
   args[0] = SECCOMP_PARM1(ctx);
   args[1] = SECCOMP_PARM2(ctx);
   args[2] = SECCOMP_PARM3(ctx);
   args[3] = SECCOMP_PARM4(ctx);
   args[4] = SECCOMP_PARM5(ctx);
   args[5] = SECCOMP_PARM6(ctx);
 
-  LOG_ERROR("seccomp sandbox violation: pid %u, syscall %lu, args %lu %lu %lu"
-            " %lu %lu %lu.  Killing process.", getpid(), syscall,
+  LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu"
+            " %lu %lu %lu.  Killing process.", pid, syscall_nr,
             args[0], args[1], args[2], args[3], args[4], args[5]);
 
+  bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
+  if (!dumped) {
+    LOG_ERROR("Failed to write minidump");
+  }
+
+  // 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);
   _exit(127);
 }
 
 /**
  * The reporter is called when the process receives a SIGSYS signal.
  * The signal is sent by the kernel when Seccomp encounter a system call
  * that has not been allowed.
  * We register an action for that signal (calling the Reporter function).
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/18-bug945498-expose-handle-signal.patch
@@ -0,0 +1,28 @@
+commit 443e11243cf3c88087b70602822d9e228f60d40a
+Author: Jed Davis <jld@mozilla.com>
+Date:   Wed Jan 29 12:06:33 2014 -0800
+
+    Bug 945498: Use breakpad to report seccomp violations as crashes.
+
+diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
+index 7155419..c0039bc 100644
+--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
+@@ -219,6 +219,9 @@ class ExceptionHandler {
+ 
+   // Force signal handling for the specified signal.
+   bool SimulateSignalDelivery(int sig);
++
++  // Report a crash signal from an SA_SIGINFO signal handler.
++  bool HandleSignal(int sig, siginfo_t* info, void* uc);
+  private:
+   // Save the old signal handlers and install new ones.
+   static bool InstallHandlersLocked();
+@@ -231,7 +234,6 @@ class ExceptionHandler {
+   void WaitForContinueSignal();
+ 
+   static void SignalHandler(int sig, siginfo_t* info, void* uc);
+-  bool HandleSignal(int sig, siginfo_t* info, void* uc);
+   static int ThreadEntry(void* arg);
+   bool DoDump(pid_t crashing_process, const void* context,
+               size_t context_size);
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
@@ -214,29 +214,31 @@ class ExceptionHandler {
   // to be copied to the minidump when a crash happens.
   void RegisterAppMemory(void* ptr, size_t length);
 
   // Unregister a block of memory that was registered with RegisterAppMemory.
   void UnregisterAppMemory(void* ptr);
 
   // Force signal handling for the specified signal.
   bool SimulateSignalDelivery(int sig);
+
+  // Report a crash signal from an SA_SIGINFO signal handler.
+  bool HandleSignal(int sig, siginfo_t* info, void* uc);
  private:
   // Save the old signal handlers and install new ones.
   static bool InstallHandlersLocked();
   // Restore the old signal handlers.
   static void RestoreHandlersLocked();
 
   void PreresolveSymbols();
   bool GenerateDump(CrashContext *context);
   void SendContinueSignalToChild();
   void WaitForContinueSignal();
 
   static void SignalHandler(int sig, siginfo_t* info, void* uc);
-  bool HandleSignal(int sig, siginfo_t* info, void* uc);
   static int ThreadEntry(void* arg);
   bool DoDump(pid_t crashing_process, const void* context,
               size_t context_size);
 
   const FilterCallback filter_;
   const MinidumpCallback callback_;
   void* const callback_context_;
 
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1734,16 +1734,23 @@ nsresult WriteMinidumpForException(EXCEP
 {
   if (!gExceptionHandler)
     return NS_ERROR_NOT_INITIALIZED;
 
   return gExceptionHandler->WriteMinidumpForException(aExceptionInfo) ? NS_OK : NS_ERROR_FAILURE;
 }
 #endif
 
+#ifdef XP_LINUX
+bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc)
+{
+  return gExceptionHandler->HandleSignal(signo, info, uc);
+}
+#endif
+
 #ifdef XP_MACOSX
 nsresult AppendObjCExceptionInfoToAppNotes(void *inException)
 {
   nsAutoCString excString;
   GetObjCExceptionInfo(inException, excString);
   AppendAppNotesToCrashReport(excString);
   return NS_OK;
 }
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -17,16 +17,20 @@
 #endif
 #include <windows.h>
 #endif
 
 #if defined(XP_MACOSX)
 #include <mach/mach.h>
 #endif
 
+#if defined(XP_LINUX)
+#include <signal.h>
+#endif
+
 class nsIFile;
 template<class KeyClass, class DataType> class nsDataHashtable;
 class nsCStringHashKey;
 
 namespace CrashReporter {
 nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force=false);
 nsresult UnsetExceptionHandler();
 bool     GetEnabled();
@@ -64,16 +68,19 @@ bool GetExtraFileForMinidump(nsIFile* mi
 bool AppendExtraData(const nsAString& id, const AnnotationTable& data);
 bool AppendExtraData(nsIFile* extraFile, const AnnotationTable& data);
 void RenameAdditionalHangMinidump(nsIFile* minidump, nsIFile* childMinidump,
                                   const nsACString& name);
 
 #ifdef XP_WIN32
   nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
 #endif
+#ifdef XP_LINUX
+  bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc);
+#endif
 #ifdef XP_MACOSX
   nsresult AppendObjCExceptionInfoToAppNotes(void *inException);
 #endif
 nsresult GetSubmitReports(bool* aSubmitReport);
 nsresult SetSubmitReports(bool aSubmitReport);
 
 // Out-of-process crash reporter API.