Bug 1744362 - Part 5: Access the shared section through DllServices r=handyman

Differential Revision: https://phabricator.services.mozilla.com/D164487
This commit is contained in:
Toshihito Kikuchi 2022-12-27 12:59:08 +00:00
Родитель 7f7af2303a
Коммит 99ea21dafe
15 изменённых файлов: 84 добавлений и 78 удалений

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

@ -13,6 +13,9 @@ namespace mozilla {
extern "C" MOZ_EXPORT nt::LoaderAPI* GetNtLoaderAPI(
nt::LoaderObserver* aNewObserver) {
// Make sure the caller is inside mozglue.dll - we don't want to allow
// external access to this function, as it contains details about
// the SharedSection which is used to sandbox future child processes.
const bool isCallerMozglue =
CheckForAddress(RETURN_ADDRESS(), L"mozglue.dll");
MOZ_ASSERT(isCallerMozglue);

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

@ -88,6 +88,7 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS LoaderPrivateAPIImp final
nt::AllocatedUnicodeString GetSectionName(void* aSectionAddr) final;
nt::LoaderAPI::InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() final;
nt::LoaderAPI::HandleLauncherErrorFnPtr GetHandleLauncherErrorFn() final;
nt::SharedSection* GetSharedSection() final;
// LoaderPrivateAPI
void NotifyBeginDllLoad(void** aContext,
@ -222,6 +223,10 @@ LoaderPrivateAPIImp::GetHandleLauncherErrorFn() {
return &HandleLauncherError;
}
nt::SharedSection* LoaderPrivateAPIImp::GetSharedSection() {
return &gSharedSection;
}
nt::MemorySectionNameBuf LoaderPrivateAPIImp::GetSectionNameBuffer(
void* aSectionAddr) {
const HANDLE kCurrentProcess = reinterpret_cast<HANDLE>(-1);

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

@ -247,23 +247,5 @@ LauncherVoidResult SharedSection::TransferHandle(
sizeof(remoteHandle));
}
// This exported function is invoked by SandboxBroker of xul.dll
// in order to add dependent modules to the CIG exception list.
extern "C" MOZ_EXPORT const wchar_t* GetDependentModulePaths() {
// We enable pre-spawn CIG only in early Beta or earlier for now
// because it caused a compat issue (bug 1682304 and 1704373).
#if defined(EARLY_BETA_OR_EARLIER)
const bool isCallerXul = CheckForAddress(RETURN_ADDRESS(), L"xul.dll");
MOZ_ASSERT(isCallerXul);
if (!isCallerXul) {
return nullptr;
}
return gSharedSection.GetDependentModules().data();
#else
return nullptr;
#endif
}
} // namespace freestanding
} // namespace mozilla

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

@ -7,6 +7,7 @@
#ifndef mozilla_freestanding_SharedSection_h
#define mozilla_freestanding_SharedSection_h
#include "mozilla/glue/SharedSection.h"
#include "mozilla/NativeNt.h"
#include "mozilla/interceptor/MMPolicies.h"
@ -59,7 +60,7 @@ struct MOZ_TRIVIAL_CTOR_DTOR Kernel32ExportsSolver final
// | | ... |
// | | L"" |
// +--------------------------------------------------------------+
class MOZ_TRIVIAL_CTOR_DTOR SharedSection final {
class MOZ_TRIVIAL_CTOR_DTOR SharedSection final : public nt::SharedSection {
struct Layout final {
enum class State {
kUninitialized,
@ -116,7 +117,7 @@ class MOZ_TRIVIAL_CTOR_DTOR SharedSection final {
// Map |sSectionHandle| to a copy-on-write page and return a writable pointer
// to each structure, or null if Layout failed to resolve exports.
Kernel32ExportsSolver* GetKernel32Exports();
Span<const wchar_t> GetDependentModules();
Span<const wchar_t> GetDependentModules() final override;
// Transfer |sSectionHandle| to a process associated with |aTransferMgr|.
static LauncherVoidResult TransferHandle(

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

@ -265,29 +265,6 @@ class ChildProcess final {
return 1;
}
auto getDependentModulePaths =
reinterpret_cast<const wchar_t* (*)()>(::GetProcAddress(
::GetModuleHandleW(nullptr), "GetDependentModulePaths"));
if (!getDependentModulePaths) {
printf(
"TEST-FAILED | TestCrossProcessWin | "
"Failed to get a pointer to GetDependentModulePaths - %08lx.\n",
::GetLastError());
return 1;
}
#if !defined(DEBUG)
// GetDependentModulePaths does not allow a caller other than xul.dll.
// Skip on Debug build because it hits MOZ_ASSERT.
if (getDependentModulePaths()) {
printf(
"TEST-FAILED | TestCrossProcessWin | "
"GetDependentModulePaths should return zero if the caller is "
"not xul.dll.\n");
return 1;
}
#endif // !defined(DEBUG)
if (!VerifySharedSection(gSharedSection)) {
return 1;
}

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

@ -431,20 +431,21 @@ static void AddCachedDirRule(sandbox::TargetPolicy* aPolicy,
// (e.g. when the launcher process is disabled), so the process should not
// enable pre-spawn CIG.
static const Maybe<Vector<const wchar_t*>>& GetPrespawnCigExceptionModules() {
// sDependentModules points to a shared section created in the launcher
// process and the mapped address is static in each process, so we cache
// it as a static variable instead of retrieving it every time.
// We enable pre-spawn CIG only in early Beta or earlier for now
// because it caused a compat issue (bug 1682304 and 1704373).
#if defined(EARLY_BETA_OR_EARLIER)
// The shared section contains a list of dependent modules as a
// null-delimited string. We convert it to a string vector and
// cache it to avoid converting the same data every time.
static Maybe<Vector<const wchar_t*>> sDependentModules =
[]() -> Maybe<Vector<const wchar_t*>> {
using GetDependentModulePathsFn = const wchar_t* (*)();
GetDependentModulePathsFn getDependentModulePaths =
reinterpret_cast<GetDependentModulePathsFn>(::GetProcAddress(
::GetModuleHandleW(nullptr), "GetDependentModulePaths"));
if (!getDependentModulePaths) {
RefPtr<DllServices> dllSvc(DllServices::Get());
auto sharedSection = dllSvc->GetSharedSection();
if (!sharedSection) {
return Nothing();
}
const wchar_t* arrayBase = getDependentModulePaths();
const wchar_t* arrayBase = sharedSection->GetDependentModules().data();
if (!arrayBase) {
return Nothing();
}
@ -463,6 +464,9 @@ static const Maybe<Vector<const wchar_t*>>& GetPrespawnCigExceptionModules() {
}();
return sDependentModules;
#else
return Nothing();
#endif
}
static sandbox::ResultCode InitSignedPolicyRulesToBypassCig(

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

@ -8,6 +8,7 @@
#define mozilla_LoaderAPIInterfaces_h
#include "nscore.h"
#include "mozilla/glue/SharedSection.h"
#include "mozilla/ModuleLoadInfo.h"
namespace mozilla {
@ -104,14 +105,18 @@ class NS_NO_VTABLE LoaderAPI {
*/
virtual InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() = 0;
virtual HandleLauncherErrorFnPtr GetHandleLauncherErrorFn() = 0;
virtual SharedSection* GetSharedSection() = 0;
};
struct WinLauncherFunctions final {
struct WinLauncherServices final {
nt::LoaderAPI::InitDllBlocklistOOPFnPtr mInitDllBlocklistOOP;
nt::LoaderAPI::HandleLauncherErrorFnPtr mHandleLauncherError;
SharedSection* mSharedSection;
WinLauncherFunctions()
: mInitDllBlocklistOOP(nullptr), mHandleLauncherError(nullptr) {}
WinLauncherServices()
: mInitDllBlocklistOOP(nullptr),
mHandleLauncherError(nullptr),
mSharedSection(nullptr) {}
};
} // namespace nt

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

@ -28,9 +28,8 @@ nt::LoaderAPI* ModuleLoadFrame::sLoaderAPI;
using GetNtLoaderAPIFn = decltype(&mozilla::GetNtLoaderAPI);
/* static */
void ModuleLoadFrame::StaticInit(
nt::LoaderObserver* aNewObserver,
nt::WinLauncherFunctions* aOutWinLauncherFunctions) {
void ModuleLoadFrame::StaticInit(nt::LoaderObserver* aNewObserver,
nt::WinLauncherServices* aOutWinLauncher) {
const auto pGetNtLoaderAPI = reinterpret_cast<GetNtLoaderAPIFn>(
::GetProcAddress(::GetModuleHandleW(nullptr), "GetNtLoaderAPI"));
if (!pGetNtLoaderAPI) {
@ -39,9 +38,9 @@ void ModuleLoadFrame::StaticInit(
gFallbackLoaderAPI.SetObserver(aNewObserver);
sLoaderAPI = &gFallbackLoaderAPI;
if (aOutWinLauncherFunctions) {
aOutWinLauncherFunctions->mHandleLauncherError =
[](const mozilla::LauncherError&, const char*) {};
if (aOutWinLauncher) {
aOutWinLauncher->mHandleLauncherError = [](const mozilla::LauncherError&,
const char*) {};
// We intentionally leave mInitDllBlocklistOOP null to make sure calling
// mInitDllBlocklistOOP in non-Firefox hits MOZ_RELEASE_ASSERT.
}
@ -51,11 +50,11 @@ void ModuleLoadFrame::StaticInit(
sLoaderAPI = pGetNtLoaderAPI(aNewObserver);
MOZ_ASSERT(sLoaderAPI);
if (aOutWinLauncherFunctions) {
aOutWinLauncherFunctions->mInitDllBlocklistOOP =
sLoaderAPI->GetDllBlocklistInitFn();
aOutWinLauncherFunctions->mHandleLauncherError =
if (aOutWinLauncher) {
aOutWinLauncher->mInitDllBlocklistOOP = sLoaderAPI->GetDllBlocklistInitFn();
aOutWinLauncher->mHandleLauncherError =
sLoaderAPI->GetHandleLauncherErrorFn();
aOutWinLauncher->mSharedSection = sLoaderAPI->GetSharedSection();
}
}

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

@ -26,7 +26,7 @@ class MOZ_RAII ModuleLoadFrame final {
ModuleLoadFrame& operator=(ModuleLoadFrame&&) = delete;
static void StaticInit(nt::LoaderObserver* aNewObserver,
nt::WinLauncherFunctions* aOutWinLauncherFunctions);
nt::WinLauncherServices* aOutWinLauncher);
private:
bool mAlreadyLoaded;

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

@ -0,0 +1,23 @@
/* -*- 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_glue_SharedSection_h
#define mozilla_glue_SharedSection_h
#include "nscore.h"
#include "mozilla/Span.h"
namespace mozilla::nt {
// This interface provides a way to access winlauncher's shared section
// through DllServices.
struct NS_NO_VTABLE SharedSection {
virtual Span<const wchar_t> GetDependentModules() = 0;
};
} // namespace mozilla::nt
#endif // mozilla_glue_SharedSection_h

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

@ -597,7 +597,7 @@ static WindowsDllInterceptor Kernel32Intercept;
static void GetNativeNtBlockSetWriter();
static glue::LoaderObserver gMozglueLoaderObserver;
static nt::WinLauncherFunctions gWinLauncherFunctions;
static nt::WinLauncherServices gWinLauncher;
MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags) {
if (sBlocklistInitAttempted) {
@ -607,8 +607,7 @@ MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags) {
sInitFlags = aInitFlags;
glue::ModuleLoadFrame::StaticInit(&gMozglueLoaderObserver,
&gWinLauncherFunctions);
glue::ModuleLoadFrame::StaticInit(&gMozglueLoaderObserver, &gWinLauncher);
#ifdef _M_AMD64
if (!IsWin8OrLater()) {
@ -764,7 +763,7 @@ MFBT_API void DllBlocklist_SetFullDllServices(
glue::AutoExclusiveLock lock(gDllServicesLock);
if (aSvc) {
aSvc->SetAuthenticodeImpl(GetAuthenticode());
aSvc->SetWinLauncherFunctions(gWinLauncherFunctions);
aSvc->SetWinLauncherServices(gWinLauncher);
gMozglueLoaderObserver.Forward(aSvc);
}

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

@ -58,23 +58,24 @@ class DllServicesBase : public Authenticode {
mAuthenticode = aAuthenticode;
}
void SetWinLauncherFunctions(const nt::WinLauncherFunctions& aFunctions) {
mWinLauncherFunctions = aFunctions;
void SetWinLauncherServices(const nt::WinLauncherServices& aWinLauncher) {
mWinLauncher = aWinLauncher;
}
template <typename... Args>
LauncherVoidResultWithLineInfo InitDllBlocklistOOP(Args&&... aArgs) {
MOZ_RELEASE_ASSERT(mWinLauncherFunctions.mInitDllBlocklistOOP);
return mWinLauncherFunctions.mInitDllBlocklistOOP(
std::forward<Args>(aArgs)...);
MOZ_RELEASE_ASSERT(mWinLauncher.mInitDllBlocklistOOP);
return mWinLauncher.mInitDllBlocklistOOP(std::forward<Args>(aArgs)...);
}
template <typename... Args>
void HandleLauncherError(Args&&... aArgs) {
MOZ_RELEASE_ASSERT(mWinLauncherFunctions.mHandleLauncherError);
mWinLauncherFunctions.mHandleLauncherError(std::forward<Args>(aArgs)...);
MOZ_RELEASE_ASSERT(mWinLauncher.mHandleLauncherError);
mWinLauncher.mHandleLauncherError(std::forward<Args>(aArgs)...);
}
nt::SharedSection* GetSharedSection() { return mWinLauncher.mSharedSection; }
// In debug builds we override GetBinaryOrgName to add a Gecko-specific
// assertion. OTOH, we normally do not want people overriding this function,
// so we'll make it final in the release case, thus covering all bases.
@ -112,7 +113,7 @@ class DllServicesBase : public Authenticode {
private:
Authenticode* mAuthenticode;
nt::WinLauncherFunctions mWinLauncherFunctions;
nt::WinLauncherServices mWinLauncher;
};
} // namespace detail

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

@ -79,6 +79,11 @@ FallbackLoaderAPI::GetHandleLauncherErrorFn() {
return nullptr;
}
nt::SharedSection* FallbackLoaderAPI::GetSharedSection() {
MOZ_ASSERT_UNREACHABLE("This should not be called so soon!");
return nullptr;
}
void FallbackLoaderAPI::SetObserver(nt::LoaderObserver* aLoaderObserver) {
mLoaderObserver = aLoaderObserver;
}

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

@ -26,6 +26,7 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS FallbackLoaderAPI final
nt::AllocatedUnicodeString GetSectionName(void* aSectionAddr) final;
nt::LoaderAPI::InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() final;
nt::LoaderAPI::HandleLauncherErrorFnPtr GetHandleLauncherErrorFn() final;
nt::SharedSection* GetSharedSection() final;
void SetObserver(nt::LoaderObserver* aLoaderObserver);

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

@ -51,6 +51,7 @@ EXPORTS.mozilla += [
]
EXPORTS.mozilla.glue += [
"SharedSection.h",
"WindowsDllServices.h",
]