diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp index f376e40d1621..a82a2738d446 100644 --- a/accessible/windows/msaa/LazyInstantiator.cpp +++ b/accessible/windows/msaa/LazyInstantiator.cpp @@ -11,7 +11,7 @@ #include "mozilla/a11y/Compatibility.h" #include "mozilla/a11y/Platform.h" #include "mozilla/Assertions.h" -#include "mozilla/mscom/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" #include "mozilla/mscom/Registration.h" #include "mozilla/UniquePtr.h" #include "nsAccessibilityService.h" @@ -313,7 +313,7 @@ LazyInstantiator::MaybeResolveRoot() { } if (GetAccService() || - ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) { + ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) { mWeakRootAccWrap = ResolveRootAccWrap(); if (!mWeakRootAccWrap) { return E_POINTER; diff --git a/browser/app/winlauncher/LaunchUnelevated.cpp b/browser/app/winlauncher/LaunchUnelevated.cpp index b0ba54df7908..38ee8e66986b 100644 --- a/browser/app/winlauncher/LaunchUnelevated.cpp +++ b/browser/app/winlauncher/LaunchUnelevated.cpp @@ -9,7 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/LauncherResult.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/RefPtr.h" #include "nsWindowsHelpers.h" diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h index eb9a908328dd..c6b2a58684b8 100644 --- a/dom/ipc/ContentProcess.h +++ b/dom/ipc/ContentProcess.h @@ -12,7 +12,7 @@ #include "ContentChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -39,7 +39,7 @@ class ContentProcess : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif DISALLOW_EVIL_CONSTRUCTORS(ContentProcess); diff --git a/dom/media/ipc/RDDProcessImpl.h b/dom/media/ipc/RDDProcessImpl.h index a75f1934758e..8c044132da34 100644 --- a/dom/media/ipc/RDDProcessImpl.h +++ b/dom/media/ipc/RDDProcessImpl.h @@ -8,7 +8,7 @@ #include "mozilla/ipc/ProcessChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif #include "RDDParent.h" diff --git a/dom/plugins/ipc/PluginProcessChild.h b/dom/plugins/ipc/PluginProcessChild.h index 48d3bc066a76..b715f0d649a0 100644 --- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -11,7 +11,7 @@ #include "mozilla/plugins/PluginModuleChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -40,7 +40,7 @@ class PluginProcessChild : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) /* Drag-and-drop depends on the host initializing COM. * This object initializes and configures COM. */ - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif PluginModuleChild mPlugin; diff --git a/gfx/ipc/GPUProcessImpl.h b/gfx/ipc/GPUProcessImpl.h index a76aeb406b33..a205e2b2333b 100644 --- a/gfx/ipc/GPUProcessImpl.h +++ b/gfx/ipc/GPUProcessImpl.h @@ -10,7 +10,7 @@ #include "GPUParent.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -33,7 +33,7 @@ class GPUProcessImpl final : public ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif }; diff --git a/ipc/mscom/ApartmentRegion.h b/ipc/mscom/ApartmentRegion.h new file mode 100644 index 000000000000..dc56e3fc9676 --- /dev/null +++ b/ipc/mscom/ApartmentRegion.h @@ -0,0 +1,94 @@ +/* -*- 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_ApartmentRegion_h +#define mozilla_mscom_ApartmentRegion_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ApartmentRegion { + public: + /** + * This constructor is to be used when we want to instantiate the object but + * we do not yet know which type of apartment we want. Call Init() to + * complete initialization. + */ + ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} + + explicit ApartmentRegion(COINIT aAptType) + : mInitResult(::CoInitializeEx(nullptr, aAptType)) { + // If this fires then we're probably mixing apartments on the same thread + MOZ_ASSERT(IsValid()); + } + + ~ApartmentRegion() { + if (IsValid()) { + ::CoUninitialize(); + } + } + + explicit operator bool() const { return IsValid(); } + + bool IsValidOutermost() const { return mInitResult == S_OK; } + + bool IsValid() const { return SUCCEEDED(mInitResult); } + + bool Init(COINIT aAptType) { + MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); + mInitResult = ::CoInitializeEx(nullptr, aAptType); + MOZ_ASSERT(IsValid()); + return IsValid(); + } + + HRESULT + GetHResult() const { return mInitResult; } + + private: + ApartmentRegion(const ApartmentRegion&) = delete; + ApartmentRegion& operator=(const ApartmentRegion&) = delete; + ApartmentRegion(ApartmentRegion&&) = delete; + ApartmentRegion& operator=(ApartmentRegion&&) = delete; + + HRESULT mInitResult; +}; + +template +class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT { + public: + ApartmentRegionT() : mAptRgn(T) {} + + ~ApartmentRegionT() = default; + + explicit operator bool() const { return mAptRgn.IsValid(); } + + bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); } + + bool IsValid() const { return mAptRgn.IsValid(); } + + HRESULT GetHResult() const { return mAptRgn.GetHResult(); } + + private: + ApartmentRegionT(const ApartmentRegionT&) = delete; + ApartmentRegionT& operator=(const ApartmentRegionT&) = delete; + ApartmentRegionT(ApartmentRegionT&&) = delete; + ApartmentRegionT& operator=(ApartmentRegionT&&) = delete; + + ApartmentRegion mAptRgn; +}; + +typedef ApartmentRegionT STARegion; +typedef ApartmentRegionT MTARegion; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ApartmentRegion_h diff --git a/ipc/mscom/COMApartmentRegion.h b/ipc/mscom/COMApartmentRegion.h deleted file mode 100644 index 9fbd8c87967d..000000000000 --- a/ipc/mscom/COMApartmentRegion.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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_COMApartmentRegion_h -#define mozilla_mscom_COMApartmentRegion_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include - -namespace mozilla { -namespace mscom { - -template -class MOZ_NON_TEMPORARY_CLASS COMApartmentRegion { - public: - COMApartmentRegion() : mInitResult(::CoInitializeEx(nullptr, T)) { - // If this fires then we're probably mixing apartments on the same thread - MOZ_ASSERT(IsValid()); - } - - ~COMApartmentRegion() { - if (IsValid()) { - ::CoUninitialize(); - } - } - - bool IsValidOutermost() const { return mInitResult == S_OK; } - - bool IsValid() const { return SUCCEEDED(mInitResult); } - - HRESULT GetHResult() const { return mInitResult; } - - private: - COMApartmentRegion(const COMApartmentRegion&) = delete; - COMApartmentRegion& operator=(const COMApartmentRegion&) = delete; - COMApartmentRegion(COMApartmentRegion&&) = delete; - COMApartmentRegion& operator=(COMApartmentRegion&&) = delete; - - HRESULT mInitResult; -}; - -typedef COMApartmentRegion STARegion; -typedef COMApartmentRegion MTARegion; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_COMApartmentRegion_h diff --git a/ipc/mscom/EnsureMTA.h b/ipc/mscom/EnsureMTA.h index 690d55101e2b..7719b0f324c6 100644 --- a/ipc/mscom/EnsureMTA.h +++ b/ipc/mscom/EnsureMTA.h @@ -11,7 +11,6 @@ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/Unused.h" -#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/mscom/Utils.h" #include "nsCOMPtr.h" #include "nsIThread.h" diff --git a/ipc/mscom/MainThreadClientInfo.cpp b/ipc/mscom/MainThreadClientInfo.cpp deleted file mode 100644 index d163d05dbf8a..000000000000 --- a/ipc/mscom/MainThreadClientInfo.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- 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 "MainThreadClientInfo.h" - -#include "MainThreadUtils.h" -#include "mozilla/Assertions.h" - -#include - -namespace mozilla { -namespace mscom { - -/* static */ -HRESULT -MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) { - MOZ_ASSERT(aOutObj && NS_IsMainThread()); - *aOutObj = nullptr; - - RefPtr obj(new MainThreadClientInfo()); - - RefPtr prevFilter; - HRESULT hr = ::CoRegisterMessageFilter(obj.get(), getter_AddRefs(prevFilter)); - if (FAILED(hr)) { - return hr; - } - - obj->mPrevFilter = prevFilter.forget(); - - obj.forget(aOutObj); - return S_OK; -} - -DWORD -MainThreadClientInfo::GetLastRemoteCallThreadId() const { - MOZ_ASSERT(NS_IsMainThread()); - return mLastRemoteCallTid; -} - -HRESULT -MainThreadClientInfo::QueryInterface(REFIID aIid, void** aOutInterface) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!aOutInterface) { - return E_INVALIDARG; - } - - if (aIid == IID_IUnknown || aIid == IID_IMessageFilter) { - RefPtr filter(this); - filter.forget(aOutInterface); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG -MainThreadClientInfo::AddRef() { - MOZ_ASSERT(NS_IsMainThread()); - - return ++mRefCnt; -} - -ULONG -MainThreadClientInfo::Release() { - MOZ_ASSERT(NS_IsMainThread()); - - ULONG newCount = --mRefCnt; - if (!newCount) { - delete this; - } - return newCount; -} - -DWORD -MainThreadClientInfo::HandleInComingCall(DWORD aCallType, HTASK aCallerTid, - DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) { - MOZ_ASSERT(NS_IsMainThread()); - - // aCallerTid is an HTASK for historical reasons but is actually just a - // regular DWORD Thread ID. - mLastRemoteCallTid = - static_cast(reinterpret_cast(aCallerTid)); - - if (!mPrevFilter) { - return SERVERCALL_ISHANDLED; - } - - return mPrevFilter->HandleInComingCall(aCallType, aCallerTid, aTickCount, - aInterfaceInfo); -} - -DWORD -MainThreadClientInfo::RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return 0; - } - - return mPrevFilter->RetryRejectedCall(aCalleeTid, aTickCount, aRejectType); -} - -DWORD -MainThreadClientInfo::MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return PENDINGMSG_WAITNOPROCESS; - } - - return mPrevFilter->MessagePending(aCalleeTid, aTickCount, aPendingType); -} - -MainThreadClientInfo::MainThreadClientInfo() - : mRefCnt(0), mLastRemoteCallTid(0) { - MOZ_ASSERT(NS_IsMainThread()); -} - -void MainThreadClientInfo::Detach() { - MOZ_ASSERT(NS_IsMainThread()); - ::CoRegisterMessageFilter(mPrevFilter, nullptr); - mPrevFilter = nullptr; -} - -} // namespace mscom -} // namespace mozilla diff --git a/ipc/mscom/MainThreadClientInfo.h b/ipc/mscom/MainThreadClientInfo.h deleted file mode 100644 index e762ec9b00a2..000000000000 --- a/ipc/mscom/MainThreadClientInfo.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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_MainThreadClientInfo -#define mozilla_mscom_MainThreadClientInfo - -#include "mozilla/RefPtr.h" -#include "nsString.h" - -#include - -namespace mozilla { -namespace mscom { - -class MainThreadClientInfo final : public IMessageFilter { - public: - static HRESULT Create(MainThreadClientInfo** aOutObj); - - DWORD GetLastRemoteCallThreadId() const; - void Detach(); - - STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - STDMETHODIMP_(DWORD) - HandleInComingCall(DWORD aCallType, HTASK aCallerTid, DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) override; - STDMETHODIMP_(DWORD) - RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) override; - STDMETHODIMP_(DWORD) - MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) override; - - private: - MainThreadClientInfo(); - ~MainThreadClientInfo() = default; - - private: - ULONG mRefCnt; - RefPtr mPrevFilter; - DWORD mLastRemoteCallTid; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadClientInfo diff --git a/ipc/mscom/MainThreadRuntime.h b/ipc/mscom/MainThreadRuntime.h deleted file mode 100644 index 00cae6c1965e..000000000000 --- a/ipc/mscom/MainThreadRuntime.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- 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_MainThreadRuntime_h -#define mozilla_mscom_MainThreadRuntime_h - -#include "mozilla/Attributes.h" -#if defined(ACCESSIBILITY) -# include "mozilla/mscom/ActivationContext.h" -#endif // defined(ACCESSIBILITY) -#include "mozilla/mscom/COMApartmentRegion.h" -#include "mozilla/mscom/MainThreadClientInfo.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { -namespace mscom { - -class MOZ_NON_TEMPORARY_CLASS MainThreadRuntime { - public: - MainThreadRuntime(); - ~MainThreadRuntime(); - - explicit operator bool() const { - return mStaRegion.IsValidOutermost() && SUCCEEDED(mInitResult); - } - - MainThreadRuntime(MainThreadRuntime&) = delete; - MainThreadRuntime(MainThreadRuntime&&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&&) = delete; - - /** - * @return 0 if call is in-process or resolving the calling thread failed, - * otherwise contains the thread id of the calling thread. - */ - static DWORD GetClientThreadId(); - - private: - HRESULT InitializeSecurity(); - - HRESULT mInitResult; -#if defined(ACCESSIBILITY) - ActivationContextRegion mActCtxRgn; -#endif // defined(ACCESSIBILITY) - STARegion mStaRegion; - - RefPtr mClientInfo; - - static MainThreadRuntime* sInstance; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadRuntime_h diff --git a/ipc/mscom/MainThreadRuntime.cpp b/ipc/mscom/ProcessRuntime.cpp similarity index 52% rename from ipc/mscom/MainThreadRuntime.cpp rename to ipc/mscom/ProcessRuntime.cpp index bce1701e4891..ffbb9261d6d0 100644 --- a/ipc/mscom/MainThreadRuntime.cpp +++ b/ipc/mscom/ProcessRuntime.cpp @@ -4,21 +4,25 @@ * 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/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" -#if defined(ACCESSIBILITY) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) # include "mozilla/a11y/Compatibility.h" -#endif -#include "mozilla/ArrayUtils.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) #include "mozilla/Assertions.h" +#include "mozilla/DynamicallyLinkedFunctionPtr.h" +#include "mozilla/mscom/ProcessRuntimeShared.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" +#include "mozilla/Unused.h" +#include "mozilla/Vector.h" #include "mozilla/WindowsVersion.h" -#if defined(ACCESSIBILITY) -# include "nsExceptionHandler.h" -#endif // defined(ACCESSIBILITY) #include "nsWindowsHelpers.h" -#include "nsXULAppAPI.h" + +#if defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/EnsureMTA.h" +# include "nsThreadManager.h" +#endif // defined(MOZILLA_INTERNAL_API) #include #include @@ -28,27 +32,65 @@ // This API from oleaut32.dll is not declared in Windows SDK headers extern "C" void __cdecl SetOaNoCache(void); +#if (_WIN32_WINNT < 0x0602) +BOOL WINAPI GetProcessMitigationPolicy( + HANDLE hProcess, PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, + SIZE_T dwLength); +#endif // (_WIN32_WINNT < 0x0602) + namespace mozilla { namespace mscom { -MainThreadRuntime* MainThreadRuntime::sInstance = nullptr; - -MainThreadRuntime::MainThreadRuntime() - : mInitResult(E_UNEXPECTED) -#if defined(ACCESSIBILITY) +ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType) + : mInitResult(CO_E_NOTINITIALIZED), + mIsParentProcess(aProcessType == GeckoProcessType_Default) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId()) -#endif // defined(ACCESSIBILITY) +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) { +#if defined(MOZILLA_INTERNAL_API) + // If our process is running under Win32k lockdown, we cannot initialize + // COM with single-threaded apartments. This is because STAs create a hidden + // window, which implicitly requires user32 and Win32k, which are blocked. + // Instead we start a multi-threaded apartment and conduct our process-wide + // COM initialization on that MTA background thread. + if (IsWin32kLockedDown()) { + // It is possible that we're running so early that we might need to start + // the thread manager ourselves. + nsresult rv = nsThreadManager::get().Init(); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + if (NS_FAILED(rv)) { + return; + } + + EnsureMTA([this]() -> void { InitInsideApartment(); }); + return; + } +#endif // defined(MOZILLA_INTERNAL_API) + + // Otherwise we initialize a single-threaded apartment on the current thread. + mAptRegion.Init(COINIT_APARTMENTTHREADED); + // We must be the outermost COM initialization on this thread. The COM runtime // cannot be configured once we start manipulating objects - MOZ_ASSERT(mStaRegion.IsValidOutermost()); - if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) { + MOZ_ASSERT(mAptRegion.IsValidOutermost()); + if (!mAptRegion.IsValidOutermost()) { + mInitResult = mAptRegion.GetHResult(); return; } - // We are required to initialize security in order to configure global - // options. + InitInsideApartment(); +} + +void ProcessRuntime::InitInsideApartment() { + ProcessInitLock lock; + if (lock.IsInitialized()) { + // COM has already been initialized by a previous ProcessRuntime instance + return; + } + + // We are required to initialize security prior to configuring global options. mInitResult = InitializeSecurity(); MOZ_ASSERT(SUCCEEDED(mInitResult)); if (FAILED(mInitResult)) { @@ -76,58 +118,25 @@ MainThreadRuntime::MainThreadRuntime() return; } - if (XRE_IsParentProcess()) { - MainThreadClientInfo::Create(getter_AddRefs(mClientInfo)); - } - - MOZ_ASSERT(!sInstance); - sInstance = this; -} - -MainThreadRuntime::~MainThreadRuntime() { - if (mClientInfo) { - mClientInfo->Detach(); - } - - MOZ_ASSERT(sInstance == this); - if (sInstance == this) { - sInstance = nullptr; - } + lock.SetInitialized(); } /* static */ DWORD -MainThreadRuntime::GetClientThreadId() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_IsParentProcess(), "Unsupported outside of parent process"); - if (!XRE_IsParentProcess()) { +ProcessRuntime::GetClientThreadId() { + DWORD callerTid; + HRESULT hr = ::CoGetCallerTID(&callerTid); + // Don't return callerTid unless the call succeeded and returned S_FALSE, + // indicating that the caller originates from a different process. + if (hr != S_FALSE) { return 0; } - // Don't check for a calling executable if the caller is in-process. - // We verify this by asking COM for a call context. If none exists, then - // we must be a local call. - RefPtr serverSecurity; - if (FAILED(::CoGetCallContext(IID_IServerSecurity, - getter_AddRefs(serverSecurity)))) { - return 0; - } - - MOZ_ASSERT(sInstance); - if (!sInstance) { - return 0; - } - - MOZ_ASSERT(sInstance->mClientInfo); - if (!sInstance->mClientInfo) { - return 0; - } - - return sInstance->mClientInfo->GetLastRemoteCallThreadId(); + return callerTid; } HRESULT -MainThreadRuntime::InitializeSecurity() { +ProcessRuntime::InitializeSecurity() { HANDLE rawToken = nullptr; BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken); if (!ok) { @@ -186,7 +195,7 @@ MainThreadRuntime::InitializeSecurity() { BYTE appContainersSid[SECURITY_MAX_SID_SIZE]; DWORD appContainersSidSize = sizeof(appContainersSid); - if (XRE_IsParentProcess() && IsWin8OrLater()) { + if (mIsParentProcess && IsWin8OrLater()) { if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr, appContainersSid, &appContainersSidSize)) { return HRESULT_FROM_WIN32(::GetLastError()); @@ -195,38 +204,43 @@ MainThreadRuntime::InitializeSecurity() { // Grant access to SYSTEM, Administrators, the user, and when running as the // browser process on Windows 8+, all app containers. - EXPLICIT_ACCESS entries[] = { - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(systemSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(tokenUser.User.Sid)}}, - // appContainersSid must be the last entry in this array! - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, - reinterpret_cast(appContainersSid)}}}; + const size_t kMaxInlineEntries = 4; + mozilla::Vector entries; - ULONG numEntries = ArrayLength(entries); - if (!XRE_IsParentProcess() || !IsWin8OrLater()) { - // Exclude appContainersSid on Windows 7 and non-parent processes. - --numEntries; + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(systemSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(tokenUser.User.Sid)}}); + + if (mIsParentProcess && IsWin8OrLater()) { + Unused << entries.append( + EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, + reinterpret_cast(appContainersSid)}}); } PACL rawDacl = nullptr; - win32Error = ::SetEntriesInAcl(numEntries, entries, nullptr, &rawDacl); + win32Error = + ::SetEntriesInAclW(entries.length(), entries.begin(), nullptr, &rawDacl); if (win32Error != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(win32Error); } @@ -251,5 +265,26 @@ MainThreadRuntime::InitializeSecurity() { RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr); } +#if defined(MOZILLA_INTERNAL_API) + +/* static */ bool +ProcessRuntime::IsWin32kLockedDown() { + static const DynamicallyLinkedFunctionPtr + pGetProcessMitigationPolicy(L"kernel32.dll", "GetProcessMitigationPolicy"); + if (!pGetProcessMitigationPolicy) { + return false; + } + + PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY polInfo; + if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), + ProcessSystemCallDisablePolicy, &polInfo, sizeof(polInfo))) { + return false; + } + + return polInfo.DisallowWin32kSystemCalls; +} + +#endif // defined(MOZILLA_INTERNAL_API) + } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/ProcessRuntime.h b/ipc/mscom/ProcessRuntime.h new file mode 100644 index 000000000000..3d27e8f43d82 --- /dev/null +++ b/ipc/mscom/ProcessRuntime.h @@ -0,0 +1,61 @@ +/* -*- 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_ProcessRuntime_h +#define mozilla_mscom_ProcessRuntime_h + +#include "mozilla/Attributes.h" +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/ActivationContext.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#include "mozilla/mscom/ApartmentRegion.h" +#include "nsXULAppAPI.h" + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final { + public: +#if defined(MOZILLA_INTERNAL_API) + ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {} +#endif // defined(MOZILLA_INTERNAL_API) + + explicit ProcessRuntime(GeckoProcessType aProcessType); + ~ProcessRuntime() = default; + + explicit operator bool() const { return SUCCEEDED(mInitResult); } + + ProcessRuntime(ProcessRuntime&) = delete; + ProcessRuntime(ProcessRuntime&&) = delete; + ProcessRuntime& operator=(ProcessRuntime&) = delete; + ProcessRuntime& operator=(ProcessRuntime&&) = delete; + + /** + * @return 0 if call is in-process or resolving the calling thread failed, + * otherwise contains the thread id of the calling thread. + */ + static DWORD GetClientThreadId(); + + private: + void InitInsideApartment(); + HRESULT InitializeSecurity(); + +#if defined(MOZILLA_INTERNAL_API) + static bool IsWin32kLockedDown(); +#endif // defined(MOZILLA_INTERNAL_API) + + HRESULT mInitResult; + bool mIsParentProcess; +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ActivationContextRegion mActCtxRgn; +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ApartmentRegion mAptRegion; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntime_h diff --git a/ipc/mscom/Ptr.h b/ipc/mscom/Ptr.h index 9df05b4a0b79..98cbef684f94 100644 --- a/ipc/mscom/Ptr.h +++ b/ipc/mscom/Ptr.h @@ -16,6 +16,8 @@ #include "nsThreadUtils.h" #include "nsXULAppAPI.h" +#include + /** * The glue code in mozilla::mscom often needs to pass around interface pointers * belonging to a different apartment from the current one. We must not touch diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index 5f425ceb806b..71a3cb05f8d5 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -7,19 +7,22 @@ EXPORTS.mozilla.mscom += [ 'Aggregation.h', 'AgileReference.h', + 'ApartmentRegion.h', 'AsyncInvoker.h', - 'COMApartmentRegion.h', 'COMPtrHolder.h', 'EnsureMTA.h', - 'MainThreadClientInfo.h', - 'MainThreadRuntime.h', 'Objref.h', 'PassthruProxy.h', + 'ProcessRuntime.h', 'ProxyStream.h', 'Ptr.h', 'Utils.h', ] +DIRS += [ + 'mozglue', +] + SOURCES += [ 'VTableBuilder.c', ] @@ -27,10 +30,9 @@ SOURCES += [ UNIFIED_SOURCES += [ 'AgileReference.cpp', 'EnsureMTA.cpp', - 'MainThreadClientInfo.cpp', - 'MainThreadRuntime.cpp', 'Objref.cpp', 'PassthruProxy.cpp', + 'ProcessRuntime.cpp', 'ProxyStream.cpp', 'RegistrationAnnotator.cpp', 'Utils.cpp', diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp new file mode 100644 index 000000000000..517918f2d87c --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp @@ -0,0 +1,33 @@ +/* -*- 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/ProcessRuntimeShared.h" +#include "MozglueUtils.h" + +// We allow multiple ProcessRuntime instances to exist simultaneously (even +// on separate threads), but only one should be doing the process-wide +// initialization. These variables provide that mutual exclusion. +static mozilla::glue::Win32SRWLock gLock; +static bool gIsProcessInitialized = false; + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& +BeginProcessRuntimeInit() { + gLock.LockExclusive(); + return gIsProcessInitialized; +} + +MFBT_API void +EndProcessRuntimeInit() { + gLock.UnlockExclusive(); +} + +} // namespace detail +} // namespace mscom +} // namespace mozilla diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.h b/ipc/mscom/mozglue/ProcessRuntimeShared.h new file mode 100644 index 000000000000..a42b1b818e54 --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.h @@ -0,0 +1,54 @@ +/* -*- 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_ProcessRuntimeShared_h +#define mozilla_mscom_ProcessRuntimeShared_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/Types.h" + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& BeginProcessRuntimeInit(); +MFBT_API void EndProcessRuntimeInit(); + +} // namespace detail + +class MOZ_RAII ProcessInitLock final { + public: + ProcessInitLock() + : mIsProcessInitialized(detail::BeginProcessRuntimeInit()) { + } + + ~ProcessInitLock() { + detail::EndProcessRuntimeInit(); + } + + bool IsInitialized() const { + return mIsProcessInitialized; + } + + void SetInitialized() { + MOZ_ASSERT(!mIsProcessInitialized); + mIsProcessInitialized = true; + } + + ProcessInitLock(const ProcessInitLock&) = delete; + ProcessInitLock(ProcessInitLock&&) = delete; + ProcessInitLock operator=(const ProcessInitLock&) = delete; + ProcessInitLock operator=(ProcessInitLock&&) = delete; + + private: + bool& mIsProcessInitialized; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntimeShared_h diff --git a/ipc/mscom/mozglue/moz.build b/ipc/mscom/mozglue/moz.build new file mode 100644 index 000000000000..2d444a2e50af --- /dev/null +++ b/ipc/mscom/mozglue/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Library('mscom-mozglue') + +EXPORTS.mozilla.mscom += [ + 'ProcessRuntimeShared.h', +] + +LOCAL_INCLUDES += [ + '/mozglue/build', +] + +DEFINES['IMPL_MFBT'] = True + +UNIFIED_SOURCES += [ + 'ProcessRuntimeShared.cpp', +] diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 4a5a18c659a4..fd3db244211f 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -84,6 +84,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']: EXPORTS.mozilla.glue += [ 'WindowsDllServices.h', ] + USE_LIBS += [ + 'mscom-mozglue', + ] EXPORTS.mozilla += [ 'arm.h', diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index fc91477d20cb..9454ea1dd871 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -110,7 +110,7 @@ # include "cairo/cairo-features.h" # include "mozilla/WindowsDllBlocklist.h" # include "mozilla/WinHeaderOnlyUtils.h" -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" # include "mozilla/widget/AudioSession.h" # if defined(MOZ_LAUNCHER_PROCESS) @@ -4803,7 +4803,7 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) { // trivial COM is run in the application. Since these settings may affect // stability, we should instantiate COM ASAP so that we can ensure that these // global settings are configured before anything can interfere. - mozilla::mscom::MainThreadRuntime msCOMRuntime; + mozilla::mscom::ProcessRuntime msCOMRuntime; #endif // init diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp index 48c419828a36..32cd7d03be41 100644 --- a/widget/windows/JumpListBuilder.cpp +++ b/widget/windows/JumpListBuilder.cpp @@ -23,7 +23,7 @@ #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "mozilla/dom/Promise.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/mscom/EnsureMTA.h" #include