From 7bc5d83d88e2e2011ab3af2ffe8fed07c943cf15 Mon Sep 17 00:00:00 2001 From: Tom Ritter Date: Wed, 23 Feb 2022 15:31:11 +0000 Subject: [PATCH] Bug 1752332: Add preferences that control whether we send user data and/or crash r=KrisWright Differential Revision: https://phabricator.services.mozilla.com/D138687 --- dom/ipc/ContentParent.cpp | 23 ++++++++++++++++++++++ modules/libpref/Preferences.cpp | 11 ++++++----- modules/libpref/Preferences.h | 3 +++ modules/libpref/init/StaticPrefList.yaml | 12 +++++++++++ modules/libpref/init/StaticPrefListBegin.h | 23 ++++++++++++++-------- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 6a5cd980fb63..ebcbcc35309e 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -76,6 +76,7 @@ #include "mozilla/Components.h" #include "mozilla/Sprintf.h" #include "mozilla/StaticPrefs_dom.h" +#include "mozilla/StaticPrefs_fission.h" #include "mozilla/StaticPrefs_media.h" #include "mozilla/StaticPrefs_widget.h" #include "mozilla/StyleSheet.h" @@ -651,6 +652,23 @@ static const char* sObserverTopics[] = { "network:socket-process-crashed", }; +static const char kFissionEnforceBlockList[] = + "fission.enforceBlocklistedPrefsInSubprocesses"; +static const char kFissionOmitBlockListValues[] = + "fission.omitBlocklistedPrefsInSubprocesses"; + +static void OnFissionBlocklistPrefChange(const char* aPref, void* aData) { + if (strcmp(aPref, kFissionEnforceBlockList) == 0) { + sCrashOnBlocklistedPref = + StaticPrefs::fission_enforceBlocklistedPrefsInSubprocesses(); + } else if (strcmp(aPref, kFissionOmitBlockListValues) == 0) { + sOmitBlocklistedPrefValues = + StaticPrefs::fission_omitBlocklistedPrefsInSubprocesses(); + } else { + MOZ_CRASH("Unknown pref passed to callback"); + } +} + // PreallocateProcess is called by the PreallocatedProcessManager. // ContentParent then takes this process back within GetNewOrUsedBrowserProcess. /*static*/ already_AddRefed @@ -680,6 +698,11 @@ void ContentParent::StartUp() { BackgroundChild::Startup(); ClientManager::Startup(); + Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange, + kFissionEnforceBlockList); + Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange, + kFissionOmitBlockListValues); + #if defined(XP_LINUX) && defined(MOZ_SANDBOX) sSandboxBrokerPolicyFactory = MakeUnique(); #endif diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index f0176d197519..023918d81334 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -516,7 +516,7 @@ class Pref { MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()); - if (!XRE_IsParentProcess() && + if (!XRE_IsParentProcess() && sCrashOnBlocklistedPref && ShouldSanitizePreference(Name(), XRE_IsContentProcess())) { MOZ_CRASH_UNSAFE_PRINTF( "Should not access the preference '%s' in the Content Processes", @@ -532,7 +532,7 @@ class Pref { MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()); - if (!XRE_IsParentProcess() && + if (!XRE_IsParentProcess() && sCrashOnBlocklistedPref && ShouldSanitizePreference(Name(), XRE_IsContentProcess())) { MOZ_CRASH_UNSAFE_PRINTF( "Should not access the preference '%s' in the Content Processes", @@ -549,7 +549,7 @@ class Pref { MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()); - if (!XRE_IsParentProcess() && + if (!XRE_IsParentProcess() && sCrashOnBlocklistedPref && ShouldSanitizePreference(Name(), XRE_IsContentProcess())) { MOZ_CRASH_UNSAFE_PRINTF( "Should not access the preference '%s' in the Content Processes", @@ -581,7 +581,7 @@ class Pref { aDomPref->defaultValue() = Nothing(); } - if (mHasUserValue && !mIsSanitized) { + if (mHasUserValue && !mIsSanitized && !sOmitBlocklistedPrefValues) { aDomPref->userValue() = Some(dom::PrefValue()); mUserValue.ToDomPrefValue(Type(), &aDomPref->userValue().ref()); } else { @@ -589,7 +589,8 @@ class Pref { } MOZ_ASSERT(aDomPref->defaultValue().isNothing() || - aDomPref->userValue().isNothing() || mIsSanitized || + aDomPref->userValue().isNothing() || + (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())); } diff --git a/modules/libpref/Preferences.h b/modules/libpref/Preferences.h index 0282647d956d..521f702fbb36 100644 --- a/modules/libpref/Preferences.h +++ b/modules/libpref/Preferences.h @@ -532,6 +532,9 @@ class Preferences final : public nsIPrefService, static bool InitStaticMembers(); }; +static Atomic sOmitBlocklistedPrefValues(false); +static Atomic sCrashOnBlocklistedPref(false); + bool ShouldSanitizePreference(const char* aPref, bool aIsContentProcess = true); } // namespace mozilla diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index d718a5b712eb..551e521df35e 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -4663,6 +4663,18 @@ value: false mirror: always +# If true, do not sent blocklisted preference values to the subprocess +- name: fission.omitBlocklistedPrefsInSubprocesses + type: RelaxedAtomicBool + value: false + mirror: always + +# If true, crash when a blocklisted preference is accessed in a subprocess +- name: fission.enforceBlocklistedPrefsInSubprocesses + type: RelaxedAtomicBool + value: false + mirror: always + #--------------------------------------------------------------------------- # Prefs starting with "font." #--------------------------------------------------------------------------- diff --git a/modules/libpref/init/StaticPrefListBegin.h b/modules/libpref/init/StaticPrefListBegin.h index 70f5886b061d..8af91795549b 100644 --- a/modules/libpref/init/StaticPrefListBegin.h +++ b/modules/libpref/init/StaticPrefListBegin.h @@ -22,7 +22,8 @@ namespace StaticPrefs { #define ALWAYS_PREF(name, base_id, full_id, cpp_type, default_value) \ extern cpp_type sMirror_##full_id; \ inline StripAtomic full_id() { \ - if (!XRE_IsParentProcess() && IsString::value) { \ + if (!XRE_IsParentProcess() && IsString::value && \ + sCrashOnBlocklistedPref) { \ MOZ_DIAGNOSTIC_ASSERT( \ !ShouldSanitizePreference(name, XRE_IsContentProcess()), \ "Should not access the preference '" name "' in Content Processes"); \ @@ -36,11 +37,17 @@ namespace StaticPrefs { inline StripAtomic GetPrefDefault_##base_id() { \ return default_value; \ } -#define ONCE_PREF(name, base_id, full_id, cpp_type, default_value) \ - extern cpp_type sMirror_##full_id; \ - inline cpp_type full_id() { \ - MaybeInitOncePrefs(); \ - return sMirror_##full_id; \ - } \ - inline const char* GetPrefName_##base_id() { return name; } \ +#define ONCE_PREF(name, base_id, full_id, cpp_type, default_value) \ + extern cpp_type sMirror_##full_id; \ + inline cpp_type full_id() { \ + MaybeInitOncePrefs(); \ + if (!XRE_IsParentProcess() && IsString::value && \ + sCrashOnBlocklistedPref) { \ + MOZ_DIAGNOSTIC_ASSERT( \ + !ShouldSanitizePreference(name, XRE_IsContentProcess()), \ + "Should not access the preference '" name "' in Content Processes"); \ + } \ + return sMirror_##full_id; \ + } \ + inline const char* GetPrefName_##base_id() { return name; } \ inline cpp_type GetPrefDefault_##base_id() { return default_value; }