From cd1c25bb790ec2cd8c87be71366605318e815665 Mon Sep 17 00:00:00 2001 From: Haik Aftandilian Date: Mon, 6 May 2019 06:09:10 +0000 Subject: [PATCH] Bug 1546544 - Enable TCSM r=asuth,spohl,mccr8 Differential Revision: https://phabricator.services.mozilla.com/D29046 --HG-- extra : moz-landing-system : lando --- netwerk/base/ProxyAutoConfig.cpp | 8 +++ netwerk/base/moz.build | 5 ++ security/sandbox/mac/SandboxPolicyContent.h | 5 ++ toolkit/xre/moz.build | 1 + xpcom/base/CycleCollectedJSRuntime.cpp | 10 ++++ xpcom/base/nsMacUtilsImpl.cpp | 62 +++++++++++++++++++++ xpcom/base/nsMacUtilsImpl.h | 17 ++++++ 7 files changed, 108 insertions(+) diff --git a/netwerk/base/ProxyAutoConfig.cpp b/netwerk/base/ProxyAutoConfig.cpp index 6469c0a62697..8e88fadd664f 100644 --- a/netwerk/base/ProxyAutoConfig.cpp +++ b/netwerk/base/ProxyAutoConfig.cpp @@ -27,6 +27,10 @@ #include "nsServiceManagerUtils.h" #include "nsNetCID.h" +#if defined(XP_MACOSX) +# include "nsMacUtilsImpl.h" +#endif + namespace mozilla { namespace net { @@ -682,6 +686,10 @@ nsresult ProxyAutoConfig::SetupJS() { mJSNeedsSetup = false; MOZ_ASSERT(!GetRunning(), "JIT is running"); +#if defined(XP_MACOSX) + nsMacUtilsImpl::EnableTCSMIfAvailable(); +#endif + delete mJSContext; mJSContext = nullptr; diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index d1e8105d5ab3..c26aa9d832bd 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -314,5 +314,10 @@ LOCAL_INCLUDES += [ '/netwerk/url-classifier', ] +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + LOCAL_INCLUDES += [ + '/xpcom/base', + ] + if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += ['-Wno-error=shadow'] diff --git a/security/sandbox/mac/SandboxPolicyContent.h b/security/sandbox/mac/SandboxPolicyContent.h index 78817124b629..c84b55100fff 100644 --- a/security/sandbox/mac/SandboxPolicyContent.h +++ b/security/sandbox/mac/SandboxPolicyContent.h @@ -105,6 +105,8 @@ static const char SandboxPolicyContent[] = R"SANDBOX_LITERAL( (sysctl-name "kern.osversion") (sysctl-name "kern.osrelease") (sysctl-name "kern.version") + (sysctl-name "kern.tcsm_available") + (sysctl-name "kern.tcsm_enable") ; TODO: remove "kern.hostname". Without it the tests hang, but the hostname ; is arguably sensitive information, so we should see what can be done about ; removing it. @@ -140,6 +142,9 @@ static const char SandboxPolicyContent[] = R"SANDBOX_LITERAL( (sysctl-name "machdep.cpu.stepping") (sysctl-name "debug.intel.gstLevelGST") (sysctl-name "debug.intel.gstLoaderControl"))) + (if (> macosMinorVersion 9) + (allow sysctl-write + (sysctl-name "kern.tcsm_enable"))) (define (home-regex home-relative-regex) (regex (string-append "^" (regex-quote home-path) home-relative-regex))) diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build index 74da5242bdeb..a9a8b430bed6 100644 --- a/toolkit/xre/moz.build +++ b/toolkit/xre/moz.build @@ -238,6 +238,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': LOCAL_INCLUDES += [ '/widget', '/widget/cocoa', + '/xpcom/base', ] CXXFLAGS += CONFIG['TK_CFLAGS'] diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 2d05057ebe1d..b6f8f2a92c1d 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -92,6 +92,10 @@ # include "ProfilerMarkerPayload.h" #endif +#if defined(XP_MACOSX) +# include "nsMacUtilsImpl.h" +#endif + #include "nsIException.h" #include "nsThread.h" #include "nsThreadUtils.h" @@ -485,6 +489,12 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSContext* aCx) MOZ_ASSERT(aCx); MOZ_ASSERT(mJSRuntime); +#if defined(XP_MACOSX) + if (!XRE_IsE10sParentProcess()) { + nsMacUtilsImpl::EnableTCSMIfAvailable(); + } +#endif + if (!JS_AddExtraGCRootsTracer(aCx, TraceBlackJS, this)) { MOZ_CRASH("JS_AddExtraGCRootsTracer failed"); } diff --git a/xpcom/base/nsMacUtilsImpl.cpp b/xpcom/base/nsMacUtilsImpl.cpp index fdc9da7952f9..11339131ba38 100644 --- a/xpcom/base/nsMacUtilsImpl.cpp +++ b/xpcom/base/nsMacUtilsImpl.cpp @@ -17,16 +17,21 @@ #include "prenv.h" #include +#include NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils) using mozilla::StaticMutexAutoLock; +using mozilla::Unused; #if defined(MOZ_SANDBOX) StaticAutoPtr nsMacUtilsImpl::sCachedAppPath; StaticMutex nsMacUtilsImpl::sCachedAppPathMutex; #endif +// Initialize with Unknown until we've checked if TCSM is available to set +Atomic nsMacUtilsImpl::sTCSMStatus(TCSM_Unknown); + nsresult nsMacUtilsImpl::GetArchString(nsAString& aArchString) { if (!mBinaryArchs.IsEmpty()) { aArchString.Assign(mBinaryArchs); @@ -241,3 +246,60 @@ nsresult nsMacUtilsImpl::GetDirectoryPath(const char* aPath, } # endif /* DEBUG */ #endif /* MOZ_SANDBOX */ + +/* static */ +bool nsMacUtilsImpl::IsTCSMAvailable() { + if (sTCSMStatus == TCSM_Unknown) { + uint32_t oldVal = 0; + size_t oldValSize = sizeof(oldVal); + int rv = sysctlbyname("kern.tcsm_available", &oldVal, &oldValSize, NULL, 0); + TCSMStatus newStatus; + if (rv < 0 || oldVal == 0) { + newStatus = TCSM_Unavailable; + } else { + newStatus = TCSM_Available; + } + // The value of sysctl kern.tcsm_available is the same for all + // threads within the same process. If another thread raced with us + // and initialized sTCSMStatus first (changing it from + // TCSM_Unknown), we can continue without needing to update it + // again. Hence, we ignore compareExchange's return value. + Unused << sTCSMStatus.compareExchange(TCSM_Unknown, newStatus); + } + return (sTCSMStatus == TCSM_Available); +} + +/* static */ +nsresult nsMacUtilsImpl::EnableTCSM() { + uint32_t newVal = 1; + int rv = sysctlbyname("kern.tcsm_enable", NULL, 0, &newVal, sizeof(newVal)); + if (rv < 0) { + return NS_ERROR_UNEXPECTED; + } + return NS_OK; +} + +/* + * Intentionally return void so that failures will be ignored in non-debug + * builds. This method uses new sysctls which may not be as thoroughly tested + * and we don't want to cause crashes handling the failure due to an OS bug. + */ +/* static */ +void nsMacUtilsImpl::EnableTCSMIfAvailable() { + if (IsTCSMAvailable()) { + if (NS_FAILED(EnableTCSM())) { + NS_WARNING("Failed to enable TCSM"); + } + MOZ_ASSERT(IsTCSMEnabled()); + } +} + +#if defined(DEBUG) +/* static */ +bool nsMacUtilsImpl::IsTCSMEnabled() { + uint32_t oldVal = 0; + size_t oldValSize = sizeof(oldVal); + int rv = sysctlbyname("kern.tcsm_enable", &oldVal, &oldValSize, NULL, 0); + return (rv == 0) && (oldVal != 0); +} +#endif diff --git a/xpcom/base/nsMacUtilsImpl.h b/xpcom/base/nsMacUtilsImpl.h index fd2c34bf8d4d..761cf17a2599 100644 --- a/xpcom/base/nsMacUtilsImpl.h +++ b/xpcom/base/nsMacUtilsImpl.h @@ -9,10 +9,12 @@ #include "nsIMacUtils.h" #include "nsString.h" +#include "mozilla/Atomics.h" #include "mozilla/Attributes.h" #include "mozilla/StaticMutex.h" #include "mozilla/StaticPtr.h" +using mozilla::Atomic; using mozilla::StaticAutoPtr; using mozilla::StaticMutex; @@ -33,6 +35,8 @@ class nsMacUtilsImpl final : public nsIMacUtils { # endif /* DEBUG */ #endif /* MOZ_SANDBOX */ + static void EnableTCSMIfAvailable(); + private: ~nsMacUtilsImpl() {} @@ -48,6 +52,19 @@ class nsMacUtilsImpl final : public nsIMacUtils { // For thread safe setting/checking of sCachedAppPath static StaticMutex sCachedAppPathMutex; #endif + + enum TCSMStatus { + TCSM_Unknown = 0, + TCSM_Available, + TCSM_Unavailable + }; + static mozilla::Atomic sTCSMStatus; + + static bool IsTCSMAvailable(); + static nsresult EnableTCSM(); +#if defined(DEBUG) + static bool IsTCSMEnabled(); +#endif }; // Global singleton service