Bug 1723204: Infrastructure for causing a crash at most N times r=KrisWright,ckerschb
☠☠ backed out by ca61528fd603 ☠ ☠
authorTom Ritter <tom@mozilla.com>
Mon, 09 Aug 2021 14:42:31 +0000
changeset 588222 2ee6c94f35b3c7cc387247c186a238071004421d
parent 588221 bbdde1587188792b36359538f5a15fa9917a297a
child 588223 83e5baac01a9ca24f16d971a7a89aa32650bdf3c
push id147715
push usertritter@mozilla.com
push dateMon, 09 Aug 2021 14:44:59 +0000
treeherderautoland@83e5baac01a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersKrisWright, ckerschb
bugs1723204
milestone92.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 1723204: Infrastructure for causing a crash at most N times r=KrisWright,ckerschb Differential Revision: https://phabricator.services.mozilla.com/D121416
dom/security/nsContentSecurityUtils.cpp
modules/libpref/Preferences.h
--- a/dom/security/nsContentSecurityUtils.cpp
+++ b/dom/security/nsContentSecurityUtils.cpp
@@ -400,16 +400,66 @@ FilenameTypeAndDetails nsContentSecurity
                                     Some(strSanitizedPath));
     }
   }
 #endif
 
   return FilenameTypeAndDetails(kOther, Nothing());
 }
 
+#ifdef NIGHTLY_BUILD
+// Crash String must be safe from a telemetry point of view.
+// This will be ensured when this function is used.
+void PossiblyCrash(const char* pref_suffix, const nsCString crash_string) {
+  if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {
+    // We only crash in the parent (unfortunately) because it's
+    // the only place we can be sure that our only-crash-once
+    // pref-writing works.
+    return;
+  }
+
+  nsCString previous_crashes("security.crash_tracking.");
+  previous_crashes.Append(pref_suffix);
+  previous_crashes.Append(".prevCrashes");
+
+  nsCString max_crashes("security.crash_tracking.");
+  max_crashes.Append(pref_suffix);
+  max_crashes.Append(".maxCrashes");
+
+  int32_t numberOfPreviousCrashes = 0;
+  numberOfPreviousCrashes = Preferences::GetInt(previous_crashes.get(), 0);
+
+  int32_t maxAllowableCrashes = 0;
+  maxAllowableCrashes = Preferences::GetInt(max_crashes.get(), 0);
+
+  if (numberOfPreviousCrashes >= maxAllowableCrashes) {
+    return;
+  }
+
+  nsresult rv =
+      Preferences::SetInt(previous_crashes.get(), ++numberOfPreviousCrashes);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  nsCOMPtr<nsIPrefService> prefsCom = Preferences::GetService();
+  Preferences* prefs = static_cast<Preferences*>(prefsCom.get());
+
+  if (!prefs->AllowOffMainThreadSave()) {
+    // Do not crash if we can't save prefs off the main thread
+    return;
+  }
+
+  rv = prefs->SavePrefFileBlocking();
+  if (!NS_FAILED(rv)) {
+    MOZ_CRASH_UNSAFE_PRINTF("%s", crash_string.get());
+  }
+}
+#endif
+
 class EvalUsageNotificationRunnable final : public Runnable {
  public:
   EvalUsageNotificationRunnable(bool aIsSystemPrincipal,
                                 NS_ConvertUTF8toUTF16& aFileNameA,
                                 uint64_t aWindowID, uint32_t aLineNumber,
                                 uint32_t aColumnNumber)
       : mozilla::Runnable("EvalUsageNotificationRunnable"),
         mIsSystemPrincipal(aIsSystemPrincipal),
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -416,16 +416,19 @@ class Preferences final : public nsIPref
 
   // Explicitly choosing synchronous or asynchronous (if allowed) preferences
   // file write. Only for the default file.  The guarantee for the "blocking"
   // is that when it returns, the file on disk reflect the current state of
   // preferences.
   nsresult SavePrefFileBlocking();
   nsresult SavePrefFileAsynchronous();
 
+  // If this is false, only blocking writes, on main thread are allowed.
+  bool AllowOffMainThreadSave();
+
  private:
   virtual ~Preferences();
 
   nsresult NotifyServiceObservers(const char* aSubject);
 
   // Loads the prefs.js file from the profile, or creates a new one. Returns
   // the prefs file if successful, or nullptr on failure.
   already_AddRefed<nsIFile> ReadSavedPrefs();
@@ -437,19 +440,16 @@ class Preferences final : public nsIPref
 
   // Default pref file save can be blocking or not.
   enum class SaveMethod { Blocking, Asynchronous };
 
   // Off main thread is only respected for the default aFile value (nullptr).
   nsresult SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod);
   nsresult WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod);
 
-  // If this is false, only blocking writes, on main thread are allowed.
-  bool AllowOffMainThreadSave();
-
   // Helpers for implementing
   // Register(Prefix)Callback/Unregister(Prefix)Callback.
  public:
   // Public so the ValueObserver classes can use it.
   enum MatchKind {
     PrefixMatch,
     ExactMatch,
   };