Bug 1511438 Part 2: Enable win32k lockdown on RDD process. r=jimm
authorBob Owen <bobowencode@gmail.com>
Tue, 29 Jan 2019 08:49:13 +0000
changeset 455738 55a7c08b3b67c472266f383b14cc4ca3803849c9
parent 455737 3a9c07fcc2ebb478ab21740f9d10d1af914bdac7
child 455739 e6a0832f3b1192a550136835d25550783afcbf04
push id111543
push userbobowencode@gmail.com
push dateTue, 29 Jan 2019 08:49:43 +0000
treeherdermozilla-inbound@55a7c08b3b67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1511438
milestone67.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 1511438 Part 2: Enable win32k lockdown on RDD process. r=jimm This stops the use of some win32k calls during start-up that will fail and in some cases cause a crash. It also moves the MITIGATION_DYNAMIC_CODE_DISABLE to be enabled after start-up. This is required because the hooks to fake the user32 and gdi32 initialization are applied as the DLLs load and the dynamic code disable blocks that.
browser/app/profile/firefox.js
dom/media/ipc/RDDProcessImpl.h
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
toolkit/xre/nsAppRunner.cpp
widget/windows/nsAppShell.cpp
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1036,20 +1036,21 @@ pref("security.sandbox.windows.log.stack
 
 // This controls the strength of the Windows GPU process sandbox.  Changes
 // will require restart.
 // For information on what the level number means, see
 // SetSecurityLevelForGPUProcess() in
 // security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
 pref("security.sandbox.gpu.level", 0);
 
-// Controls whether we disable win32k for the GMP processes.
+// Controls whether we disable win32k for the processes.
 // true means that win32k system calls are not permitted.
-// Note: win32k is currently _not_ disabled due to intermittent test failures,
-// where the GMP process fails very early. See bug 1449348.
+pref("security.sandbox.rdd.win32k-disable", true);
+// Note: win32k is currently _not_ disabled for GMP due to intermittent test
+// failures, where the GMP process fails very early. See bug 1449348.
 pref("security.sandbox.gmp.win32k-disable", false);
 #endif
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
 // Start the Mac sandbox early during child process startup instead
 // of when messaged by the parent after the message loop is running.
 pref("security.sandbox.content.mac.earlyinit", true);
 #endif
--- a/dom/media/ipc/RDDProcessImpl.h
+++ b/dom/media/ipc/RDDProcessImpl.h
@@ -24,18 +24,13 @@ class RDDProcessImpl final : public ipc:
 
   bool Init(int aArgc, char* aArgv[]) override;
   void CleanUp() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RDDProcessImpl);
 
   RDDParent mRDD;
-
-#if defined(XP_WIN)
-  // This object initializes and configures COM.
-  mozilla::mscom::MainThreadRuntime mCOMRuntime;
-#endif
 };
 
 }  // namespace mozilla
 
 #endif  // _include_dom_media_ipc_RDDProcessImpl_h__
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -47,16 +47,17 @@ static UniquePtr<nsString> sPluginTempDi
 static UniquePtr<nsString> sRoamingAppDataDir;
 static UniquePtr<nsString> sLocalAppDataDir;
 static UniquePtr<nsString> sUserExtensionsDevDir;
 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
 static UniquePtr<nsString> sUserExtensionsDir;
 #endif
 
 // Cached prefs which are needed off main thread.
+static bool sRddWin32kDisable = false;
 static bool sGmpWin32kDisable = false;
 
 static LazyLogModule sSandboxBrokerLog("SandboxBroker");
 
 #define LOG_E(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Error, (__VA_ARGS__))
 #define LOG_W(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Warning, (__VA_ARGS__))
 
 // Used to store whether we have accumulated an error combination for this
@@ -124,16 +125,18 @@ void SandboxBroker::GeckoDependentInitia
 #endif
 
   // Create sLaunchErrors up front because ClearOnShutdown must be called on the
   // main thread.
   sLaunchErrors = MakeUnique<nsTHashtable<nsCStringHashKey>>();
   ClearOnShutdown(&sLaunchErrors);
 
   // Cache prefs that are needed off main thread.
+  Preferences::AddBoolVarCache(&sRddWin32kDisable,
+                               "security.sandbox.rdd.win32k-disable");
   Preferences::AddBoolVarCache(&sGmpWin32kDisable,
                                "security.sandbox.gmp.win32k-disable");
 }
 
 SandboxBroker::SandboxBroker() {
   if (sBrokerService) {
     scoped_refptr<sandbox::TargetPolicy> policy =
         sBrokerService->CreatePolicy();
@@ -720,23 +723,31 @@ bool SandboxBroker::SetSecurityLevelForR
   SANDBOX_ENSURE_SUCCESS(result,
                          "SetDelayedIntegrityLevel should never fail with "
                          "these arguments, what happened?");
 
   sandbox::MitigationFlags mitigations =
       sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_HEAP_TERMINATE |
       sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
       sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
-      sandbox::MITIGATION_DYNAMIC_CODE_DISABLE |
       sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32;
 
+  if (sRddWin32kDisable) {
+    mitigations |= sandbox::MITIGATION_WIN32K_DISABLE;
+    result =
+        mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN,
+                         sandbox::TargetPolicy::FAKE_USER_GDI_INIT, nullptr);
+    SANDBOX_ENSURE_SUCCESS(result, "Failed to set FAKE_USER_GDI_INIT policy.");
+  }
+
   result = mPolicy->SetProcessMitigations(mitigations);
   SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
 
   mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
+                sandbox::MITIGATION_DYNAMIC_CODE_DISABLE |
                 sandbox::MITIGATION_DLL_SEARCH_ORDER;
 
   result = mPolicy->SetDelayedProcessMitigations(mitigations);
   SANDBOX_ENSURE_SUCCESS(result,
                          "Invalid flags for SetDelayedProcessMitigations.");
 
   // Add the policy for the client side of a pipe. It is just a file
   // in the \pipe\ namespace. We restrict it to pipes that start with
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4709,17 +4709,17 @@ bool XRE_IsE10sParentProcess() {
 #define GECKO_PROCESS_TYPE(enum_name, string_name, xre_name)     \
   bool XRE_Is##xre_name##Process() {                             \
     return XRE_GetProcessType() == GeckoProcessType_##enum_name; \
   }
 #include "mozilla/GeckoProcessTypes.h"
 #undef GECKO_PROCESS_TYPE
 
 bool XRE_UseNativeEventProcessing() {
-#ifdef XP_MACOSX
+#if defined(XP_MACOSX) || defined(XP_WIN)
   if (XRE_IsRDDProcess() || XRE_IsSocketProcess()) {
     return false;
   }
 #endif
   if (XRE_IsContentProcess()) {
     static bool sInited = false;
     static bool sUseNativeEventProcessing = false;
     if (!sInited) {
--- a/widget/windows/nsAppShell.cpp
+++ b/widget/windows/nsAppShell.cpp
@@ -318,19 +318,21 @@ nsAppShell::Observe(nsISupports* aSubjec
 
 nsresult nsAppShell::Init() {
   LSPAnnotate();
 
   hal::Init();
 
   mozilla::ipc::windows::InitUIThread();
 
-  sTaskbarButtonCreatedMsg = ::RegisterWindowMessageW(kTaskbarButtonEventId);
-  NS_ASSERTION(sTaskbarButtonCreatedMsg,
-               "Could not register taskbar button creation message");
+  if (XRE_Win32kCallsAllowed()) {
+    sTaskbarButtonCreatedMsg = ::RegisterWindowMessageW(kTaskbarButtonEventId);
+    NS_ASSERTION(sTaskbarButtonCreatedMsg,
+                 "Could not register taskbar button creation message");
+  }
 
   // The hidden message window is used for interrupting the processing of native
   // events, so that we can process gecko events. Therefore, we only need it if
   // we are processing native events.
   if (XRE_UseNativeEventProcessing()) {
     mLastNativeEventScheduled = TimeStamp::NowLoRes();
 
     WNDCLASSW wc;
@@ -349,17 +351,17 @@ nsresult nsAppShell::Init() {
       wc.lpszMenuName = (LPCWSTR) nullptr;
       wc.lpszClassName = kWindowClass;
       RegisterClassW(&wc);
     }
 
     mEventWnd = CreateWindowW(kWindowClass, L"nsAppShell:EventWindow", 0, 0, 0,
                               10, 10, HWND_MESSAGE, nullptr, module, nullptr);
     NS_ENSURE_STATE(mEventWnd);
-  } else {
+  } else if (XRE_IsContentProcess()) {
     // We're not generally processing native events, but still using GDI and we
     // still have some internal windows, e.g. from calling CoInitializeEx.
     // So we use a class that will do a single event pump where previously we
     // might have processed multiple events to make sure any occasional messages
     // to these windows are processed. This also allows any internal Windows
     // messages to be processed to ensure the GDI data remains fresh.
     nsCOMPtr<nsIThreadInternal> threadInt =
         do_QueryInterface(NS_GetCurrentThread());