From dd6526daaee22eee64cb71d2b4af1eea552ddc76 Mon Sep 17 00:00:00 2001 From: Nia Alarie Date: Thu, 12 Sep 2024 09:42:44 +0200 Subject: [PATCH 1/4] js: Support for the MPROTECT security feature (PaX and NetBSD) On such platforms, remapping memory that was once writable to executable is forbidden unless the initial mmap() is declared to change in such a way using the PROT_MPROTECT macro. --- js/src/jit/ProcessExecutableMemory.cpp | 15 ++++++++++++++- js/src/vm/ArrayBufferObject.cpp | 7 ++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/js/src/jit/ProcessExecutableMemory.cpp b/js/src/jit/ProcessExecutableMemory.cpp index 7c40d93c71..d9e7c28f66 100644 --- a/js/src/jit/ProcessExecutableMemory.cpp +++ b/js/src/jit/ProcessExecutableMemory.cpp @@ -287,8 +287,15 @@ ReserveProcessExecutableMemory(size_t bytes) // Note that randomAddr is just a hint: if the address is not available // mmap will pick a different address. void* randomAddr = ComputeRandomAllocationAddress(); +#ifdef PROT_MPROTECT + void* p = MozTaggedAnonymousMmap(randomAddr, bytes, + PROT_MPROTECT(PROT_EXEC | PROT_WRITE | PROT_READ), + MAP_PRIVATE | MAP_ANON, + -1, 0, "js-executable-memory"); +#else void* p = MozTaggedAnonymousMmap(randomAddr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0, "js-executable-memory"); +#endif if (p == MAP_FAILED) return nullptr; return p; @@ -315,7 +322,13 @@ ProtectionSettingToFlags(ProtectionSetting protection) static void CommitPages(void* addr, size_t bytes, ProtectionSetting protection) { - void* p = MozTaggedAnonymousMmap(addr, bytes, ProtectionSettingToFlags(protection), + void* p = MozTaggedAnonymousMmap(addr, bytes, +#ifdef PROT_MPROTECT + ProtectionSettingToFlags(protection) | + PROT_MPROTECT(PROT_EXEC | PROT_WRITE | PROT_READ), +#else + ProtectionSettingToFlags(protection), +#endif MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0, "js-executable-memory"); MOZ_RELEASE_ASSERT(addr == p); diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 6ace034adb..06e31f208c 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -644,7 +644,12 @@ WasmArrayRawBuffer::Allocate(uint32_t numBytes, Maybe maxSize) return nullptr; } # else // XP_WIN - void* data = MozTaggedAnonymousMmap(nullptr, (size_t) mappedSizeWithHeader, PROT_NONE, + void* data = MozTaggedAnonymousMmap(nullptr, (size_t) mappedSizeWithHeader, +#ifdef PROT_MPROTECT + PROT_MPROTECT(PROT_EXEC | PROT_WRITE | PROT_READ), +#else + PROT_NONE, +#endif MAP_PRIVATE | MAP_ANON, -1, 0, "wasm-reserved"); if (data == MAP_FAILED) return nullptr; From 09b3c7a2d8f30b849f1f845733e20d7b6aa694a8 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Thu, 25 Jan 2024 13:40:39 +0800 Subject: [PATCH 2/4] Issue #2578 - Part 1: Implement preference for controlling same-origin policy --- caps/nsScriptSecurityManager.cpp | 8 +++++++- caps/nsScriptSecurityManager.h | 1 + modules/libpref/init/all.js | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index e7dedba8fa..7394bf0f74 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -76,6 +76,7 @@ nsIIOService *nsScriptSecurityManager::sIOService = nullptr; nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr; JSContext *nsScriptSecurityManager::sContext = nullptr; bool nsScriptSecurityManager::sStrictFileOriginPolicy = true; +bool nsScriptSecurityManager::sSameOriginPolicy = true; /////////////////////////// // Convenience Functions // @@ -607,7 +608,7 @@ nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI, nsIURI* aTargetURI, bool reportError) { - if (!SecurityCompareURIs(aSourceURI, aTargetURI)) + if (sSameOriginPolicy && !SecurityCompareURIs(aSourceURI, aTargetURI)) { if (reportError) { ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), @@ -1434,10 +1435,13 @@ nsScriptSecurityManager::CanGetService(JSContext *cx, const char sJSEnabledPrefName[] = "javascript.enabled"; const char sFileOriginPolicyPrefName[] = "security.fileuri.strict_origin_policy"; +const char sSameOriginPolicyPrefName[] = + "security.same_origin_policy.enabled"; static const char* kObservedPrefs[] = { sJSEnabledPrefName, sFileOriginPolicyPrefName, + sSameOriginPolicyPrefName, "capability.policy.", nullptr }; @@ -1593,6 +1597,8 @@ nsScriptSecurityManager::ScriptSecurityPrefChanged() Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled); sStrictFileOriginPolicy = Preferences::GetBool(sFileOriginPolicyPrefName, false); + sSameOriginPolicy = + Preferences::GetBool(sSameOriginPolicyPrefName, true); mFileURIWhitelist.reset(); } diff --git a/caps/nsScriptSecurityManager.h b/caps/nsScriptSecurityManager.h index b1953291db..1455276538 100644 --- a/caps/nsScriptSecurityManager.h +++ b/caps/nsScriptSecurityManager.h @@ -152,6 +152,7 @@ private: } static bool sStrictFileOriginPolicy; + static bool sSameOriginPolicy; static nsIIOService *sIOService; static nsIStringBundle *sStrBundle; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ab47fed8b7..d687d9faf9 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1338,6 +1338,9 @@ pref("javascript.options.streams", true); pref("advanced.mailftp", false); pref("image.animation_mode", "normal"); +// Same-origin policy for all URIs. +pref("security.same_origin_policy.enabled", true); + // Same-origin policy for file URIs, "false" is traditional pref("security.fileuri.strict_origin_policy", true); From 2d60c5492627f6296542a8bf9a86d2a7aa04dc45 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Thu, 25 Jan 2024 13:48:31 +0800 Subject: [PATCH 3/4] Issue #2578 - Part 2: Implement preference for disabling CORS preflight requests if CORS is disabled --- netwerk/protocol/http/nsCORSListenerProxy.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/netwerk/protocol/http/nsCORSListenerProxy.cpp b/netwerk/protocol/http/nsCORSListenerProxy.cpp index a06a0df55e..8d4cd487ba 100644 --- a/netwerk/protocol/http/nsCORSListenerProxy.cpp +++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp @@ -53,6 +53,7 @@ using namespace mozilla; static bool gDisableCORS = false; static bool gDisableCORSPrivateData = false; +static bool gBypassCORSPreflightRequest = false; static void LogBlockedRequest(nsIRequest* aRequest, @@ -414,6 +415,8 @@ nsCORSListenerProxy::Startup() "content.cors.disable"); Preferences::AddBoolVarCache(&gDisableCORSPrivateData, "content.cors.no_private_data"); + Preferences::AddBoolVarCache(&gBypassCORSPreflightRequest, + "content.cors.bypass_preflight_request"); } /* static */ @@ -543,6 +546,9 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest) } if (gDisableCORS) { + if (gBypassCORSPreflightRequest) { + return NS_OK; + } LogBlockedRequest(aRequest, "CORSDisabled", nullptr); return NS_ERROR_DOM_BAD_URI; } @@ -1413,6 +1419,10 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel, *aPreflightChannel = nullptr; if (gDisableCORS) { + if (gBypassCORSPreflightRequest) { + aCallback->OnPreflightSucceeded(); + return NS_OK; + } LogBlockedRequest(aRequestChannel, "CORSDisabled", nullptr); return NS_ERROR_DOM_BAD_URI; } From 290489eddac04714a6e79b788648760bb98bc880 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Thu, 12 Sep 2024 23:56:51 +0800 Subject: [PATCH 4/4] Issue #2578 - Part 3: Expose CORS and CORS bypass preflight requests preferences. --- modules/libpref/init/all.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index d687d9faf9..1960cda652 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1222,6 +1222,12 @@ pref("dom.cycle_collector.incremental", false); pref("content.sink.pending_event_mode", 0); #endif +// Is support for CORS enabled? +pref("content.cors.disable", false); + +// Should preflight requests be bypassed when CORS is disabled? +pref("content.cors.bypass_preflight_request", false); + // Disable popups from plugins by default // 0 = openAllowed // 1 = openControlled