From 8b6ae9572767923951fde9bbf8d0bd7f3ec7835e Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Wed, 15 Sep 2021 10:21:04 +0000 Subject: [PATCH] Bug 1546154 p3: Explicitly load COM functions from combase.dll to prevent ole32 loading. r=Jamie Differential Revision: https://phabricator.services.mozilla.com/D124931 --- browser/app/winlauncher/moz.build | 1 + ipc/mscom/ApartmentRegion.h | 9 ++-- ipc/mscom/COMWrappers.cpp | 73 +++++++++++++++++++++++++++++++ ipc/mscom/COMWrappers.h | 44 +++++++++++++++++++ ipc/mscom/EnsureMTA.cpp | 50 +++++++-------------- ipc/mscom/ProcessRuntime.cpp | 9 ++-- ipc/mscom/Utils.cpp | 10 ++--- ipc/mscom/moz.build | 2 + ipc/mscom/oop/moz.build | 1 + mozglue/misc/moz.build | 1 + tools/lint/mscom-init.yml | 2 + xpcom/base/nsUUIDGenerator.cpp | 5 +-- 12 files changed, 157 insertions(+), 50 deletions(-) create mode 100644 ipc/mscom/COMWrappers.cpp create mode 100644 ipc/mscom/COMWrappers.h diff --git a/browser/app/winlauncher/moz.build b/browser/app/winlauncher/moz.build index 654e6eacbbd1..f182d3f67b82 100644 --- a/browser/app/winlauncher/moz.build +++ b/browser/app/winlauncher/moz.build @@ -9,6 +9,7 @@ Library("winlauncher") FORCE_STATIC_LIB = True UNIFIED_SOURCES += [ + "/ipc/mscom/COMWrappers.cpp", "/ipc/mscom/ProcessRuntime.cpp", "/toolkit/xre/WinTokenUtils.cpp", "/widget/windows/WindowsConsole.cpp", diff --git a/ipc/mscom/ApartmentRegion.h b/ipc/mscom/ApartmentRegion.h index aa4d3e6d418f..41915710df8a 100644 --- a/ipc/mscom/ApartmentRegion.h +++ b/ipc/mscom/ApartmentRegion.h @@ -9,8 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" - -#include +#include "mozilla/mscom/COMWrappers.h" namespace mozilla { namespace mscom { @@ -25,14 +24,14 @@ class MOZ_NON_TEMPORARY_CLASS ApartmentRegion final { constexpr ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} explicit ApartmentRegion(COINIT aAptType) - : mInitResult(::CoInitializeEx(nullptr, aAptType)) { + : mInitResult(wrapped::CoInitializeEx(nullptr, aAptType)) { // If this fires then we're probably mixing apartments on the same thread MOZ_ASSERT(IsValid()); } ~ApartmentRegion() { if (IsValid()) { - ::CoUninitialize(); + wrapped::CoUninitialize(); } } @@ -44,7 +43,7 @@ class MOZ_NON_TEMPORARY_CLASS ApartmentRegion final { bool Init(COINIT aAptType) { MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); - mInitResult = ::CoInitializeEx(nullptr, aAptType); + mInitResult = wrapped::CoInitializeEx(nullptr, aAptType); MOZ_ASSERT(IsValid()); return IsValid(); } diff --git a/ipc/mscom/COMWrappers.cpp b/ipc/mscom/COMWrappers.cpp new file mode 100644 index 000000000000..aa986af83329 --- /dev/null +++ b/ipc/mscom/COMWrappers.cpp @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "mozilla/mscom/COMWrappers.h" + +#include "mozilla/Assertions.h" +#include "mozilla/DynamicallyLinkedFunctionPtr.h" + +namespace mozilla::mscom::wrapped { + +HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit) { + static const StaticDynamicallyLinkedFunctionPtr + pCoInitializeEx(L"combase.dll", "CoInitializeEx"); + return pCoInitializeEx(pvReserved, dwCoInit); +} + +void CoUninitialize() { + static const StaticDynamicallyLinkedFunctionPtr + pCoUninitialize(L"combase.dll", "CoUninitialize"); + return pCoUninitialize(); +} + +HRESULT CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE* pCookie) { + static const StaticDynamicallyLinkedFunctionPtr< + decltype(&::CoIncrementMTAUsage)> + pCoIncrementMTAUsage(L"combase.dll", "CoIncrementMTAUsage"); + // This API is only available beginning with Windows 8. + if (!pCoIncrementMTAUsage) { + return E_NOTIMPL; + } + + HRESULT hr = pCoIncrementMTAUsage(pCookie); + MOZ_ASSERT(SUCCEEDED(hr)); + return hr; +} + +HRESULT CoGetApartmentType(APTTYPE* pAptType, APTTYPEQUALIFIER* pAptQualifier) { + static const StaticDynamicallyLinkedFunctionPtr< + decltype(&::CoGetApartmentType)> + pCoGetApartmentType(L"combase.dll", "CoGetApartmentType"); + return pCoGetApartmentType(pAptType, pAptQualifier); +} + +HRESULT CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc, + SOLE_AUTHENTICATION_SERVICE* asAuthSvc, + void* pReserved1, DWORD dwAuthnLevel, + DWORD dwImpLevel, void* pAuthList, + DWORD dwCapabilities, void* pReserved3) { + static const StaticDynamicallyLinkedFunctionPtr< + decltype(&::CoInitializeSecurity)> + pCoInitializeSecurity(L"combase.dll", "CoInitializeSecurity"); + return pCoInitializeSecurity(pSecDesc, cAuthSvc, asAuthSvc, pReserved1, + dwAuthnLevel, dwImpLevel, pAuthList, + dwCapabilities, pReserved3); +} + +HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, + DWORD dwClsContext, REFIID riid, LPVOID* ppv) { + static const StaticDynamicallyLinkedFunctionPtr + pCoCreateInstance(L"combase.dll", "CoCreateInstance"); + return pCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); +} + +HRESULT CoCreateGuid(GUID* pguid) { + static const StaticDynamicallyLinkedFunctionPtr + pCoCreateGuid(L"combase.dll", "CoCreateGuid"); + return pCoCreateGuid(pguid); +} + +} // namespace mozilla::mscom::wrapped diff --git a/ipc/mscom/COMWrappers.h b/ipc/mscom/COMWrappers.h new file mode 100644 index 000000000000..8a89d07ac28a --- /dev/null +++ b/ipc/mscom/COMWrappers.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 mozilla_mscom_COMWrappers_h +#define mozilla_mscom_COMWrappers_h + +#include + +#if (NTDDI_VERSION < NTDDI_WIN8) +// Win8+ API that we use very carefully +DECLARE_HANDLE(CO_MTA_USAGE_COOKIE); +HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE* pCookie); +#endif // (NTDDI_VERSION < NTDDI_WIN8) + +// A set of wrapped COM functions, so that we can dynamically link to the +// functions in combase.dll. This prevents ole32.dll and many other DLLs +// loading, which are not required when we have win32k locked down. +namespace mozilla::mscom::wrapped { + +HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); + +void CoUninitialize(); + +HRESULT CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE* pCookie); + +HRESULT CoGetApartmentType(APTTYPE* pAptType, APTTYPEQUALIFIER* pAptQualifier); + +HRESULT CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc, + SOLE_AUTHENTICATION_SERVICE* asAuthSvc, + void* pReserved1, DWORD dwAuthnLevel, + DWORD dwImpLevel, void* pAuthList, + DWORD dwCapabilities, void* pReserved3); + +HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, + DWORD dwClsContext, REFIID riid, LPVOID* ppv); + +HRESULT CoCreateGuid(GUID* pguid); + +} // namespace mozilla::mscom::wrapped + +#endif // mozilla_mscom_COMWrappers_h diff --git a/ipc/mscom/EnsureMTA.cpp b/ipc/mscom/EnsureMTA.cpp index c34bfcf3de04..a7d33545501d 100644 --- a/ipc/mscom/EnsureMTA.cpp +++ b/ipc/mscom/EnsureMTA.cpp @@ -9,6 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/DebugOnly.h" +#include "mozilla/mscom/COMWrappers.h" #include "mozilla/mscom/Utils.h" #include "mozilla/SchedulerGroup.h" #include "mozilla/StaticLocalPtr.h" @@ -17,14 +18,6 @@ #include "private/pprthred.h" -#include - -#if (NTDDI_VERSION < NTDDI_WIN8) -// Win8+ API that we use very carefully -DECLARE_HANDLE(CO_MTA_USAGE_COOKIE); -HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE* pCookie); -#endif // (NTDDI_VERSION < NTDDI_WIN8) - namespace { class EnterMTARunnable : public mozilla::Runnable { @@ -32,7 +25,7 @@ class EnterMTARunnable : public mozilla::Runnable { EnterMTARunnable() : mozilla::Runnable("EnterMTARunnable") {} NS_IMETHOD Run() override { mozilla::DebugOnly hr = - ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); + mozilla::mscom::wrapped::CoInitializeEx(nullptr, COINIT_MULTITHREADED); MOZ_ASSERT(SUCCEEDED(hr)); return NS_OK; } @@ -52,7 +45,7 @@ class BackgroundMTAData { if (mThread) { mThread->Dispatch( NS_NewRunnableFunction("BackgroundMTAData::~BackgroundMTAData", - &::CoUninitialize), + &mozilla::mscom::wrapped::CoUninitialize), NS_DISPATCH_NORMAL); mThread->Shutdown(); } @@ -80,28 +73,19 @@ EnsureMTA::EnsureMTA() { // We intentionally don't check rv unless we need it when // CoIncremementMTAUsage is unavailable. - // This API is only available beginning with Windows 8. Even though this - // constructor will only be called once, we intentionally use - // StaticDynamicallyLinkedFunctionPtr here to hang onto the ole32 module. - static const StaticDynamicallyLinkedFunctionPtr< - decltype(&::CoIncrementMTAUsage)> - pCoIncrementMTAUsage(L"ole32.dll", "CoIncrementMTAUsage"); - if (pCoIncrementMTAUsage) { - // Calling this function initializes the MTA without needing to explicitly - // create a thread and call CoInitializeEx to do it. - // We don't retain the cookie because once we've incremented the MTA, we - // leave it that way for the lifetime of the process. - CO_MTA_USAGE_COOKIE mtaCookie = nullptr; - HRESULT hr = pCoIncrementMTAUsage(&mtaCookie); - MOZ_ASSERT(SUCCEEDED(hr)); - if (SUCCEEDED(hr)) { - if (NS_SUCCEEDED(rv)) { - // Start the persistent MTA thread (mostly) asynchronously. - Unused << GetPersistentMTAThread(); - } - - return; + // Calling this function initializes the MTA without needing to explicitly + // create a thread and call CoInitializeEx to do it. + // We don't retain the cookie because once we've incremented the MTA, we + // leave it that way for the lifetime of the process. + CO_MTA_USAGE_COOKIE mtaCookie = nullptr; + HRESULT hr = wrapped::CoIncrementMTAUsage(&mtaCookie); + if (SUCCEEDED(hr)) { + if (NS_SUCCEEDED(rv)) { + // Start the persistent MTA thread (mostly) asynchronously. + Unused << GetPersistentMTAThread(); } + + return; } // In the fallback case, we simply initialize our persistent MTA thread. @@ -128,8 +112,8 @@ EnsureMTA::CreateInstanceInternal(REFCLSID aClsid, REFIID aIid) { MOZ_ASSERT(IsCurrentThreadExplicitMTA()); RefPtr iface; - HRESULT hr = ::CoCreateInstance(aClsid, nullptr, CLSCTX_INPROC_SERVER, aIid, - getter_AddRefs(iface)); + HRESULT hr = wrapped::CoCreateInstance(aClsid, nullptr, CLSCTX_INPROC_SERVER, + aIid, getter_AddRefs(iface)); if (FAILED(hr)) { return CreateInstanceAgileRefPromise::CreateAndReject(hr, __func__); } diff --git a/ipc/mscom/ProcessRuntime.cpp b/ipc/mscom/ProcessRuntime.cpp index 4baa5fcece88..bb957b1a5d50 100644 --- a/ipc/mscom/ProcessRuntime.cpp +++ b/ipc/mscom/ProcessRuntime.cpp @@ -13,6 +13,7 @@ // defined(MOZ_HAS_MOZGLUE)) #include "mozilla/Assertions.h" #include "mozilla/DynamicallyLinkedFunctionPtr.h" +#include "mozilla/mscom/COMWrappers.h" #include "mozilla/mscom/ProcessRuntimeShared.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" @@ -287,9 +288,9 @@ void ProcessRuntime::InitInsideApartment() { if (prevInitState < ProcessInitState::PartialGlobalOptions) { RefPtr globalOpts; - mInitResult = - ::CoCreateInstance(CLSID_GlobalOptions, nullptr, CLSCTX_INPROC_SERVER, - IID_IGlobalOptions, getter_AddRefs(globalOpts)); + mInitResult = wrapped::CoCreateInstance( + CLSID_GlobalOptions, nullptr, CLSCTX_INPROC_SERVER, IID_IGlobalOptions, + getter_AddRefs(globalOpts)); MOZ_ASSERT(SUCCEEDED(mInitResult)); if (FAILED(mInitResult)) { return; @@ -468,7 +469,7 @@ ProcessRuntime::InitializeSecurity(const ProcessCategory aProcessCategory) { return HRESULT_FROM_WIN32(::GetLastError()); } - return ::CoInitializeSecurity( + return wrapped::CoInitializeSecurity( &sd, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr); } diff --git a/ipc/mscom/Utils.cpp b/ipc/mscom/Utils.cpp index 24092ee26216..377bbeba5c81 100644 --- a/ipc/mscom/Utils.cpp +++ b/ipc/mscom/Utils.cpp @@ -17,13 +17,13 @@ #endif #include "mozilla/ArrayUtils.h" +#include "mozilla/mscom/COMWrappers.h" #include "mozilla/DebugOnly.h" #include "mozilla/mscom/Objref.h" #include "mozilla/mscom/Utils.h" #include "mozilla/RefPtr.h" #include "mozilla/WindowsVersion.h" -#include #include #include #include @@ -40,14 +40,14 @@ namespace mscom { bool IsCOMInitializedOnCurrentThread() { APTTYPE aptType; APTTYPEQUALIFIER aptTypeQualifier; - HRESULT hr = CoGetApartmentType(&aptType, &aptTypeQualifier); + HRESULT hr = wrapped::CoGetApartmentType(&aptType, &aptTypeQualifier); return hr != CO_E_NOTINITIALIZED; } bool IsCurrentThreadMTA() { APTTYPE aptType; APTTYPEQUALIFIER aptTypeQualifier; - HRESULT hr = CoGetApartmentType(&aptType, &aptTypeQualifier); + HRESULT hr = wrapped::CoGetApartmentType(&aptType, &aptTypeQualifier); if (FAILED(hr)) { return false; } @@ -58,7 +58,7 @@ bool IsCurrentThreadMTA() { bool IsCurrentThreadExplicitMTA() { APTTYPE aptType; APTTYPEQUALIFIER aptTypeQualifier; - HRESULT hr = CoGetApartmentType(&aptType, &aptTypeQualifier); + HRESULT hr = wrapped::CoGetApartmentType(&aptType, &aptTypeQualifier); if (FAILED(hr)) { return false; } @@ -70,7 +70,7 @@ bool IsCurrentThreadExplicitMTA() { bool IsCurrentThreadImplicitMTA() { APTTYPE aptType; APTTYPEQUALIFIER aptTypeQualifier; - HRESULT hr = CoGetApartmentType(&aptType, &aptTypeQualifier); + HRESULT hr = wrapped::CoGetApartmentType(&aptType, &aptTypeQualifier); if (FAILED(hr)) { return false; } diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index e4568a82a3e7..d615bd82d3a6 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -10,6 +10,7 @@ EXPORTS.mozilla.mscom += [ "ApartmentRegion.h", "AsyncInvoker.h", "COMPtrHolder.h", + "COMWrappers.h", "EnsureMTA.h", "Objref.h", "PassthruProxy.h", @@ -30,6 +31,7 @@ SOURCES += [ UNIFIED_SOURCES += [ "AgileReference.cpp", + "COMWrappers.cpp", "EnsureMTA.cpp", "Objref.cpp", "PassthruProxy.cpp", diff --git a/ipc/mscom/oop/moz.build b/ipc/mscom/oop/moz.build index c3a30fc6d034..5ead655e6fe4 100644 --- a/ipc/mscom/oop/moz.build +++ b/ipc/mscom/oop/moz.build @@ -8,6 +8,7 @@ Library("mscom_oop") SOURCES += [ "../ActivationContext.cpp", + "../COMWrappers.cpp", "../Objref.cpp", "../Registration.cpp", "../StructStream.cpp", diff --git a/mozglue/misc/moz.build b/mozglue/misc/moz.build index 070e1f6f97ab..634db3d298e1 100644 --- a/mozglue/misc/moz.build +++ b/mozglue/misc/moz.build @@ -79,6 +79,7 @@ if CONFIG["OS_ARCH"] == "WINNT": if not CONFIG["JS_STANDALONE"]: SOURCES += [ + "/ipc/mscom/COMWrappers.cpp", "/ipc/mscom/ProcessRuntime.cpp", "PreXULSkeletonUI.cpp", ] diff --git a/tools/lint/mscom-init.yml b/tools/lint/mscom-init.yml index 043cc1012428..c2be80747d98 100644 --- a/tools/lint/mscom-init.yml +++ b/tools/lint/mscom-init.yml @@ -20,6 +20,8 @@ forbid-mscom-init: exclude: # These files are the only allowable locations - ipc/mscom/ApartmentRegion.h + - ipc/mscom/COMWrappers.cpp + - ipc/mscom/COMWrappers.h - ipc/mscom/ProcessRuntime.cpp - ipc/mscom/EnsureMTA.cpp # These files are existing locations that must eventually be fixed. diff --git a/xpcom/base/nsUUIDGenerator.cpp b/xpcom/base/nsUUIDGenerator.cpp index 7b491db5cd72..7ee09f2d0732 100644 --- a/xpcom/base/nsUUIDGenerator.cpp +++ b/xpcom/base/nsUUIDGenerator.cpp @@ -5,8 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(XP_WIN) -# include -# include +# include "mozilla/mscom/COMWrappers.h" #elif defined(XP_MACOSX) # include #else @@ -95,7 +94,7 @@ nsUUIDGenerator::GenerateUUIDInPlace(nsID* aId) { MutexAutoLock lock(mLock); #if defined(XP_WIN) - HRESULT hr = CoCreateGuid((GUID*)aId); + HRESULT hr = mozilla::mscom::wrapped::CoCreateGuid((GUID*)aId); if (FAILED(hr)) { return NS_ERROR_FAILURE; }