Bug 1546154 p3: Explicitly load COM functions from combase.dll to prevent ole32 loading. r=Jamie

Differential Revision: https://phabricator.services.mozilla.com/D124931
This commit is contained in:
Bob Owen 2021-09-20 10:09:01 +00:00
parent 31688610ce
commit 972b41f513
12 changed files with 185 additions and 50 deletions

View File

@ -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",

View File

@ -9,8 +9,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include <objbase.h>
#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();
}

101
ipc/mscom/COMWrappers.cpp Normal file
View File

@ -0,0 +1,101 @@
/* -*- 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 <objbase.h>
#include "mozilla/Assertions.h"
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
namespace mozilla::mscom::wrapped {
HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit) {
static const StaticDynamicallyLinkedFunctionPtr<decltype(&::CoInitializeEx)>
pCoInitializeEx(L"combase.dll", "CoInitializeEx");
if (!pCoInitializeEx) {
return ::CoInitializeEx(pvReserved, dwCoInit);
}
return pCoInitializeEx(pvReserved, dwCoInit);
}
void CoUninitialize() {
static const StaticDynamicallyLinkedFunctionPtr<decltype(&::CoUninitialize)>
pCoUninitialize(L"combase.dll", "CoUninitialize");
if (!pCoUninitialize) {
return ::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");
if (!pCoGetApartmentType) {
return ::CoGetApartmentType(pAptType, pAptQualifier);
}
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");
if (!pCoInitializeSecurity) {
return ::CoInitializeSecurity(pSecDesc, cAuthSvc, asAuthSvc, pReserved1,
dwAuthnLevel, dwImpLevel, pAuthList,
dwCapabilities, pReserved3);
}
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<decltype(&::CoCreateInstance)>
pCoCreateInstance(L"combase.dll", "CoCreateInstance");
if (!pCoCreateInstance) {
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
}
return pCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
}
HRESULT CoCreateGuid(GUID* pguid) {
static const StaticDynamicallyLinkedFunctionPtr<decltype(&::CoCreateGuid)>
pCoCreateGuid(L"combase.dll", "CoCreateGuid");
if (!pCoCreateGuid) {
return ::CoCreateGuid(pguid);
}
return pCoCreateGuid(pguid);
}
} // namespace mozilla::mscom::wrapped

44
ipc/mscom/COMWrappers.h Normal file
View File

@ -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 <objbase.h>
#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 on win8+. 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

View File

@ -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 <combaseapi.h>
#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<HRESULT> 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<IUnknown> 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__);
}

View File

@ -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<IGlobalOptions> 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);
}

View File

@ -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 <objbase.h>
#include <objidl.h>
#include <shlwapi.h>
#include <winnt.h>
@ -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;
}

View File

@ -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",

View File

@ -8,6 +8,7 @@ Library("mscom_oop")
SOURCES += [
"../ActivationContext.cpp",
"../COMWrappers.cpp",
"../Objref.cpp",
"../Registration.cpp",
"../StructStream.cpp",

View File

@ -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",
]

View File

@ -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.

View File

@ -5,8 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if defined(XP_WIN)
# include <windows.h>
# include <objbase.h>
# include "mozilla/mscom/COMWrappers.h"
#elif defined(XP_MACOSX)
# include <CoreFoundation/CoreFoundation.h>
#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;
}