Bug 1400344: Rename mscom::MainThreadRuntime to mscom::ProcessRuntime and make it aware of Win32k lockdown and of multiple instantiations; r=Jamie

This patch takes care of a bunch of issues and does some cleanup:

* We rename mscom::MainThreadRuntime to mscom::ProcessRuntime, as the latter
  is a more accurate name going forward.
* We make ProcessRuntime aware of the Win32k Lockdown process mitigation
  policy. When Win32k is disabled, we perform process-wide COM initialization
  in the multi-threaded apartment (since we cannot create an STA window).
* We refactor the mscom apartment region stuff to enable the Win32k lockdown
  pieces in ProcessRuntime.
* We move some Gecko-specific stuff into MOZILLA_INTERNAL_API guards so that
  ProcessRuntime is usable outside of xul.dll (I will be needing it for the
  launcher process).
* Another thing that might happen with the launcher process is that, under
  error conditions in the launcher, we create a ProcessRuntime object on a
  background thread for the purposes of telemetry logging, but we also allow
  the main thread to proceed to start as the browser. This could result in a
  scenario where the main thread, as the browser process, is attempting to
  instantiate its ProcessRuntime and ends up racing with the launcher process's
  telemetry thread which has its own ProcessRuntime. To account for this
  situation, we add mutual exclusion to the process-wide initialization code.
  We host this part inside mozglue since that state is shared between both
  firefox.exe and xul.dll.
* We clean up ProcessRuntime::InitializeSecurity by using Vector to set up
  the EXPLICIT_ACCESS entries.
* We remove mscom::MainThreadClientInfo and replace it with a direct call to
  CoGetCallerTID
* We revise all references to this class to use the new name.

Differential Revision: https://phabricator.services.mozilla.com/D19551

--HG--
rename : ipc/mscom/COMApartmentRegion.h => ipc/mscom/ApartmentRegion.h
rename : ipc/mscom/MainThreadRuntime.cpp => ipc/mscom/ProcessRuntime.cpp
rename : ipc/mscom/MainThreadRuntime.h => ipc/mscom/ProcessRuntime.h
extra : moz-landing-system : lando
This commit is contained in:
Aaron Klotz 2019-02-14 16:40:58 +00:00
Родитель 1e0e61116d
Коммит 0cb12a123a
22 изменённых файлов: 412 добавлений и 404 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 <objbase.h>
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 <COINIT T>
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<COINIT_APARTMENTTHREADED> STARegion;
typedef ApartmentRegionT<COINIT_MULTITHREADED> MTARegion;
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_ApartmentRegion_h

Просмотреть файл

@ -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 <objbase.h>
namespace mozilla {
namespace mscom {
template <COINIT T>
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<COINIT_APARTMENTTHREADED> STARegion;
typedef COMApartmentRegion<COINIT_MULTITHREADED> MTARegion;
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_COMApartmentRegion_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"

Просмотреть файл

@ -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 <objbase.h>
namespace mozilla {
namespace mscom {
/* static */
HRESULT
MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) {
MOZ_ASSERT(aOutObj && NS_IsMainThread());
*aOutObj = nullptr;
RefPtr<MainThreadClientInfo> obj(new MainThreadClientInfo());
RefPtr<IMessageFilter> 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<IMessageFilter> 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<DWORD>(reinterpret_cast<uintptr_t>(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

Просмотреть файл

@ -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 <objidl.h>
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<IMessageFilter> mPrevFilter;
DWORD mLastRemoteCallTid;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_MainThreadClientInfo

Просмотреть файл

@ -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<MainThreadClientInfo> mClientInfo;
static MainThreadRuntime* sInstance;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_MainThreadRuntime_h

Просмотреть файл

@ -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 <accctrl.h>
#include <aclapi.h>
@ -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<IServerSecurity> 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<LPWSTR>(systemSid)}},
{COM_RIGHTS_EXECUTE,
GRANT_ACCESS,
NO_INHERITANCE,
{nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID,
TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast<LPWSTR>(adminSid)}},
{COM_RIGHTS_EXECUTE,
GRANT_ACCESS,
NO_INHERITANCE,
{nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
reinterpret_cast<LPWSTR>(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<LPWSTR>(appContainersSid)}}};
const size_t kMaxInlineEntries = 4;
mozilla::Vector<EXPLICIT_ACCESS_W, kMaxInlineEntries> 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<LPWSTR>(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<LPWSTR>(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<LPWSTR>(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<LPWSTR>(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<decltype(&::GetProcessMitigationPolicy)>
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

Просмотреть файл

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

Просмотреть файл

@ -16,6 +16,8 @@
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include <objidl.h>
/**
* 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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -36,6 +36,9 @@ if CONFIG['OS_TARGET'] == 'WINNT':
'user32.dll',
]
RCINCLUDE = 'mozglue.rc'
USE_LIBS += [
'mscom-mozglue',
]
if CONFIG['MOZ_PGO'] and CONFIG['CC_TYPE'] == 'clang-cl':
SOURCES += ['cygprofile.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

Просмотреть файл

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