Bug 1546544 - Enable TCSM r=asuth,spohl,mccr8
authorHaik Aftandilian <haftandilian@mozilla.com>
Tue, 07 May 2019 22:16:14 +0000
changeset 531820 cd1ccb74af7c84aaa8ea43851c6ac74fd00ec276
parent 531819 d851ba3d3b29675ec384dba6a25de24dd8b26e28
child 531821 64ac5acae26bd63323e2f62890eae27380119bb3
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth, spohl, mccr8
bugs1546544
milestone68.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 1546544 - Enable TCSM r=asuth,spohl,mccr8 Differential Revision: https://phabricator.services.mozilla.com/D29046
netwerk/base/ProxyAutoConfig.cpp
netwerk/base/moz.build
security/sandbox/mac/SandboxPolicyContent.h
toolkit/xre/moz.build
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/nsMacUtilsImpl.cpp
xpcom/base/nsMacUtilsImpl.h
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -22,16 +22,20 @@
 #include "js/Warnings.h"  // JS::SetWarningReporter
 #include "prnetdb.h"
 #include "nsITimer.h"
 #include "mozilla/net/DNS.h"
 #include "mozilla/Utf8.h"  // mozilla::Utf8Unit
 #include "nsServiceManagerUtils.h"
 #include "nsNetCID.h"
 
+#if defined(XP_MACOSX)
+#  include "nsMacUtilsImpl.h"
+#endif
+
 namespace mozilla {
 namespace net {
 
 // These are some global helper symbols the PAC format requires that we provide
 // that are initialized as part of the global javascript context used for PAC
 // evaluations. Additionally dnsResolve(host) and myIpAddress() are supplied in
 // the same context but are implemented as c++ helpers. alert(msg) is similarly
 // defined.
@@ -677,16 +681,20 @@ nsresult ProxyAutoConfig::Init(const nsC
   mJSNeedsSetup = true;
   return NS_OK;
 }
 
 nsresult ProxyAutoConfig::SetupJS() {
   mJSNeedsSetup = false;
   MOZ_ASSERT(!GetRunning(), "JIT is running");
 
+#if defined(XP_MACOSX)
+  nsMacUtilsImpl::EnableTCSMIfAvailable();
+#endif
+
   delete mJSContext;
   mJSContext = nullptr;
 
   if (mConcatenatedPACData.IsEmpty()) return NS_ERROR_FAILURE;
 
   NS_GetCurrentThread()->SetCanInvokeJS(true);
 
   mJSContext = JSContextWrapper::Create(mExtraHeapSize);
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -309,10 +309,15 @@ FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/netwerk/protocol/http',
     '/netwerk/socket',
     '/netwerk/url-classifier',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+    LOCAL_INCLUDES += [
+        '/xpcom/base',
+    ]
+
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/security/sandbox/mac/SandboxPolicyContent.h
+++ b/security/sandbox/mac/SandboxPolicyContent.h
@@ -100,16 +100,18 @@ static const char SandboxPolicyContent[]
   (if (= macosMinorVersion 9)
     (allow sysctl-read)
     (allow sysctl-read
       (sysctl-name-regex #"^sysctl\.")
       (sysctl-name "kern.ostype")
       (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.
       (sysctl-name "kern.hostname")
       (sysctl-name "hw.machine")
       (sysctl-name "hw.model")
       (sysctl-name "hw.ncpu")
       (sysctl-name "hw.activecpu")
@@ -135,16 +137,19 @@ static const char SandboxPolicyContent[]
       (sysctl-name "hw.optional.avx1_0")
       (sysctl-name "hw.optional.avx2_0")
       (sysctl-name "machdep.cpu.vendor")
       (sysctl-name "machdep.cpu.family")
       (sysctl-name "machdep.cpu.model")
       (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)))
   (define (home-subpath home-relative-subpath)
     (subpath (string-append home-path home-relative-subpath)))
   (define (home-literal home-relative-literal)
     (literal (string-append home-path home-relative-literal)))
 
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -233,16 +233,17 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_
     USE_LIBS += [
         'mozsandbox',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     LOCAL_INCLUDES += [
         '/widget',
         '/widget/cocoa',
+        '/xpcom/base',
     ]
 
 CXXFLAGS += CONFIG['TK_CFLAGS']
 CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
 
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -87,16 +87,20 @@
 #include "nsWrapperCache.h"
 #include "nsStringBuffer.h"
 #include "GeckoProfiler.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ProfilerMarkerPayload.h"
 #endif
 
+#if defined(XP_MACOSX)
+# include "nsMacUtilsImpl.h"
+#endif
+
 #include "nsIException.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 #ifdef NIGHTLY_BUILD
 // For performance reasons, we make the JS Dev Error Interceptor a Nightly-only
 // feature.
@@ -480,16 +484,22 @@ CycleCollectedJSRuntime::CycleCollectedJ
       ,
       mShutdownCalled(false)
 #endif
 {
   MOZ_COUNT_CTOR(CycleCollectedJSRuntime);
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(mJSRuntime);
 
+#if defined(XP_MACOSX)
+  if (!XRE_IsParentProcess()) {
+    nsMacUtilsImpl::EnableTCSMIfAvailable();
+  }
+#endif
+
   if (!JS_AddExtraGCRootsTracer(aCx, TraceBlackJS, this)) {
     MOZ_CRASH("JS_AddExtraGCRootsTracer failed");
   }
   JS_SetGrayGCRootsTracer(aCx, TraceGrayJS, this);
   JS_SetGCCallback(aCx, GCCallback, this);
   mPrevGCSliceCallback = JS::SetGCSliceCallback(aCx, GCSliceCallback);
 
   if (NS_IsMainThread()) {
--- a/xpcom/base/nsMacUtilsImpl.cpp
+++ b/xpcom/base/nsMacUtilsImpl.cpp
@@ -12,26 +12,31 @@
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsIProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "prenv.h"
 
 #include <CoreFoundation/CoreFoundation.h>
+#include <sys/sysctl.h>
 
 NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils)
 
 using mozilla::StaticMutexAutoLock;
+using mozilla::Unused;
 
 #if defined(MOZ_SANDBOX)
 StaticAutoPtr<nsCString> nsMacUtilsImpl::sCachedAppPath;
 StaticMutex nsMacUtilsImpl::sCachedAppPathMutex;
 #endif
 
+// Initialize with Unknown until we've checked if TCSM is available to set
+Atomic<nsMacUtilsImpl::TCSMStatus> nsMacUtilsImpl::sTCSMStatus(TCSM_Unknown);
+
 nsresult nsMacUtilsImpl::GetArchString(nsAString& aArchString) {
   if (!mBinaryArchs.IsEmpty()) {
     aArchString.Assign(mBinaryArchs);
     return NS_OK;
   }
 
   aArchString.Truncate();
 
@@ -236,8 +241,65 @@ nsresult nsMacUtilsImpl::GetDirectoryPat
 
   if (NS_FAILED(directoryFile->GetNativePath(aDirectoryPath))) {
     MOZ_CRASH("Failed to get path for an nsIFile");
   }
   return NS_OK;
 }
 #  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
--- a/xpcom/base/nsMacUtilsImpl.h
+++ b/xpcom/base/nsMacUtilsImpl.h
@@ -4,20 +4,22 @@
  * 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/. */
 
 #ifndef nsMacUtilsImpl_h___
 #define nsMacUtilsImpl_h___
 
 #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;
 
 class nsMacUtilsImpl final : public nsIMacUtils {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMACUTILS
 
@@ -28,31 +30,46 @@ class nsMacUtilsImpl final : public nsIM
 
 #  ifdef DEBUG
   static nsresult GetBloatLogDir(nsCString& aDirectoryPath);
   static nsresult GetDirectoryPath(const char* aPath,
                                    nsCString& aDirectoryPath);
 #  endif /* DEBUG */
 #endif   /* MOZ_SANDBOX */
 
+  static void EnableTCSMIfAvailable();
+
  private:
   ~nsMacUtilsImpl() {}
 
   nsresult GetArchString(nsAString& aArchString);
 
   // A string containing a "-" delimited list of architectures
   // in our binary.
   nsString mBinaryArchs;
 
 #if defined(MOZ_SANDBOX)
   // Cache the appDir returned from GetAppPath to avoid doing I/O
   static StaticAutoPtr<nsCString> sCachedAppPath;
   // For thread safe setting/checking of sCachedAppPath
   static StaticMutex sCachedAppPathMutex;
 #endif
+
+  enum TCSMStatus {
+    TCSM_Unknown = 0,
+    TCSM_Available,
+    TCSM_Unavailable
+  };
+  static mozilla::Atomic<nsMacUtilsImpl::TCSMStatus> sTCSMStatus;
+
+  static bool IsTCSMAvailable();
+  static nsresult EnableTCSM();
+#if defined(DEBUG)
+  static bool IsTCSMEnabled();
+#endif
 };
 
 // Global singleton service
 // 697BD3FD-43E5-41CE-AD5E-C339175C0818
 #define NS_MACUTILSIMPL_CID                          \
   {                                                  \
     0x697BD3FD, 0x43E5, 0x41CE, {                    \
       0xAD, 0x5E, 0xC3, 0x39, 0x17, 0x5C, 0x08, 0x18 \