зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 13 changesets (bug 1522830) for causing xpc shell failures in test_ThirdPartyModulesPing.js CLOSED TREE
Backed out changeset a3e44bbc9ce3 (bug 1522830) Backed out changeset 11078767a246 (bug 1522830) Backed out changeset c7ee156830cf (bug 1522830) Backed out changeset 810f0cb2308d (bug 1522830) Backed out changeset f8ab75219387 (bug 1522830) Backed out changeset ec293f9a5e32 (bug 1522830) Backed out changeset 4bfc013c3d79 (bug 1522830) Backed out changeset f4ae67f2f231 (bug 1522830) Backed out changeset 2737350b7d40 (bug 1522830) Backed out changeset 52931597c652 (bug 1522830) Backed out changeset bc8985a34539 (bug 1522830) Backed out changeset 09cbbbc5c802 (bug 1522830) Backed out changeset d5e366ea4657 (bug 1522830)
This commit is contained in:
Родитель
95d3472017
Коммит
83be0128f4
|
@ -284,8 +284,7 @@ int main(int argc, char* argv[], char* envp[]) {
|
|||
// main
|
||||
if (argc > 1 && IsArg(argv[1], "contentproc")) {
|
||||
# ifdef HAS_DLL_BLOCKLIST
|
||||
DllBlocklist_Initialize(gBlocklistInitFlags |
|
||||
eDllBlocklistInitFlagIsChildProcess);
|
||||
DllBlocklist_Initialize(eDllBlocklistInitFlagIsChildProcess);
|
||||
# endif
|
||||
# if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
// We need to initialize the sandbox TargetServices before InitXPCOMGlue
|
||||
|
|
|
@ -17,25 +17,16 @@
|
|||
#include "DllBlocklistInit.h"
|
||||
#include "freestanding/DllBlocklist.h"
|
||||
|
||||
extern uint32_t gBlocklistInitFlags;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#if defined(MOZ_ASAN)
|
||||
|
||||
// This DLL blocking code is incompatible with ASAN because
|
||||
// it is able to execute before ASAN itself has even initialized.
|
||||
LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
||||
const wchar_t* aFullImagePath, HANDLE aChildProcess) {
|
||||
return mozilla::Ok();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
||||
const wchar_t* aFullImagePath, HANDLE aChildProcess) {
|
||||
LauncherVoidResult InitializeDllBlocklistOOP(const wchar_t* aFullImagePath,
|
||||
HANDLE aChildProcess) {
|
||||
CrossProcessDllInterceptor intcpt(aChildProcess);
|
||||
intcpt.Init(L"ntdll.dll");
|
||||
|
||||
|
@ -110,13 +101,6 @@ LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
|||
|
||||
// Tell the mozglue blocklist that we have bootstrapped
|
||||
uint32_t newFlags = eDllBlocklistInitFlagWasBootstrapped;
|
||||
|
||||
if (gBlocklistInitFlags & eDllBlocklistInitFlagWasBootstrapped) {
|
||||
// If we ourselves were bootstrapped, then we are starting a child process
|
||||
// and need to set the appropriate flag.
|
||||
newFlags |= eDllBlocklistInitFlagIsChildProcess;
|
||||
}
|
||||
|
||||
ok = !!::WriteProcessMemory(aChildProcess, &gBlocklistInitFlags, &newFlags,
|
||||
sizeof(newFlags), &bytesWritten);
|
||||
if (!ok || bytesWritten != sizeof(newFlags)) {
|
||||
|
@ -126,6 +110,4 @@ LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
|||
return Ok();
|
||||
}
|
||||
|
||||
#endif // defined(MOZ_ASAN)
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
||||
const wchar_t* aFullImagePath, HANDLE aChildProcess);
|
||||
LauncherVoidResult InitializeDllBlocklistOOP(const wchar_t* aFullImagePath,
|
||||
HANDLE aChildProcess);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -43,12 +43,14 @@
|
|||
static mozilla::LauncherVoidResult PostCreationSetup(
|
||||
const wchar_t* aFullImagePath, HANDLE aChildProcess,
|
||||
HANDLE aChildMainThread, const bool aIsSafeMode) {
|
||||
// The AArch64 build has not yet been tested with this.
|
||||
#if defined(_M_ARM64)
|
||||
// The launcher process's DLL blocking code is incompatible with ASAN because
|
||||
// it is able to execute before ASAN itself has even initialized.
|
||||
// Also, the AArch64 build doesn't yet have a working interceptor.
|
||||
#if defined(MOZ_ASAN) || defined(_M_ARM64)
|
||||
return mozilla::Ok();
|
||||
#else
|
||||
return mozilla::InitializeDllBlocklistOOP(aFullImagePath, aChildProcess);
|
||||
#endif // defined(_M_ARM64)
|
||||
#endif // defined(MOZ_ASAN) || defined(_M_ARM64)
|
||||
}
|
||||
|
||||
#if !defined( \
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/NativeNt.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/WindowsDllBlocklist.h"
|
||||
|
||||
#include "DllBlocklist.h"
|
||||
#include "LoaderPrivateAPI.h"
|
||||
|
@ -181,8 +180,9 @@ static BlockAction CheckBlockInfo(const DllBlockInfo* aInfo, void* aBaseAddress,
|
|||
}
|
||||
}
|
||||
|
||||
if ((aInfo->mFlags & DllBlockInfo::CHILD_PROCESSES_ONLY) &&
|
||||
!(gBlocklistInitFlags & eDllBlocklistInitFlagIsChildProcess)) {
|
||||
// We're not bootstrapping child processes at this time, so this case is
|
||||
// always true.
|
||||
if (aInfo->mFlags & DllBlockInfo::CHILD_PROCESSES_ONLY) {
|
||||
return BlockAction::Allow;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "../DllBlocklistInit.h"
|
||||
|
||||
using GlobalInitializerFn = void(__cdecl*)(void);
|
||||
|
||||
|
@ -85,7 +84,7 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS LoaderPrivateAPIImp final
|
|||
void NotifyEndDllLoad(void* aContext, NTSTATUS aLoadNtStatus,
|
||||
ModuleLoadInfo&& aModuleLoadInfo) final;
|
||||
nt::AllocatedUnicodeString GetSectionName(void* aSectionAddr) final;
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() final;
|
||||
nt::MemorySectionNameBuf GetSectionNameBuffer(void* aSectionAddr) final;
|
||||
|
||||
// LoaderPrivateAPI
|
||||
void NotifyBeginDllLoad(void** aContext,
|
||||
|
@ -94,7 +93,6 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS LoaderPrivateAPIImp final
|
|||
PCUNICODE_STRING aRequestedDllName) final;
|
||||
void SetObserver(nt::LoaderObserver* aNewObserver) final;
|
||||
bool IsDefaultObserver() const final;
|
||||
nt::MemorySectionNameBuf GetSectionNameBuffer(void* aSectionAddr) final;
|
||||
};
|
||||
|
||||
static void Init() {
|
||||
|
@ -210,11 +208,6 @@ nt::AllocatedUnicodeString LoaderPrivateAPIImp::GetSectionName(
|
|||
return nt::AllocatedUnicodeString(&buf.mSectionFileName);
|
||||
}
|
||||
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr
|
||||
LoaderPrivateAPIImp::GetDllBlocklistInitFn() {
|
||||
return &InitializeDllBlocklistOOP;
|
||||
}
|
||||
|
||||
nt::MemorySectionNameBuf LoaderPrivateAPIImp::GetSectionNameBuffer(
|
||||
void* aSectionAddr) {
|
||||
const HANDLE kCurrentProcess = reinterpret_cast<HANDLE>(-1);
|
||||
|
|
|
@ -223,7 +223,6 @@
|
|||
# define getpid _getpid
|
||||
# include "mozilla/widget/AudioSession.h"
|
||||
# include "mozilla/audio/AudioNotificationReceiver.h"
|
||||
# include "mozilla/WinDllServices.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
|
@ -1340,13 +1339,6 @@ void ContentChild::InitXPCOM(
|
|||
// background thread since we'll likely need database information very soon.
|
||||
BackgroundChild::Startup();
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// DLL services untrusted modules processing depends on
|
||||
// BackgroundChild::Startup having been called
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->StartUntrustedModulesProcessor();
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
|
||||
if (NS_WARN_IF(!actorChild)) {
|
||||
MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
|
||||
|
@ -1453,22 +1445,6 @@ mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvGetUntrustedModulesData(
|
||||
GetUntrustedModulesDataResolver&& aResolver) {
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->GetUntrustedModulesData()->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aResolver](Maybe<UntrustedModulesData>&& aData) {
|
||||
aResolver(std::move(aData));
|
||||
},
|
||||
[aResolver](nsresult aReason) { aResolver(Nothing()); });
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL(this, "Unsupported on this platform");
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild(
|
||||
const bool& aDumpAllTraces, const FileDescriptor& aGCLog,
|
||||
const FileDescriptor& aCCLog) {
|
||||
|
@ -2415,11 +2391,6 @@ void ContentChild::ActorDestroy(ActorDestroyReason why) {
|
|||
// keep persistent state.
|
||||
ProcessChild::QuickExit();
|
||||
#else
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->DisableFull();
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
if (gFirstIdleTask) {
|
||||
gFirstIdleTask->Cancel();
|
||||
gFirstIdleTask = nullptr;
|
||||
|
|
|
@ -561,9 +561,6 @@ class ContentChild final
|
|||
const uint32_t& generation, const bool& anonymize,
|
||||
const bool& minimizeMemoryUsage, const Maybe<FileDescriptor>& DMDFile);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetUntrustedModulesData(
|
||||
GetUntrustedModulesDataResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes(
|
||||
const XPCOMInitData& aXPCOMInit, const StructuredCloneData& aInitialData,
|
||||
nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache,
|
||||
|
@ -808,7 +805,7 @@ class ContentChild final
|
|||
* generated by the chrome process.
|
||||
*/
|
||||
uint32_t mMsaaID;
|
||||
#endif // defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||
#endif
|
||||
|
||||
AppInfo mAppInfo;
|
||||
|
||||
|
|
|
@ -287,7 +287,6 @@
|
|||
#ifdef XP_WIN
|
||||
# include "mozilla/audio/AudioNotificationSender.h"
|
||||
# include "mozilla/widget/AudioSession.h"
|
||||
# include "mozilla/WinDllServices.h"
|
||||
#endif
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -5801,24 +5800,6 @@ mozilla::ipc::IPCResult ContentParent::RecvNotifyMediaAudibleChanged(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvGetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority,
|
||||
GetModulesTrustResolver&& aResolver) {
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->GetModulesTrust(std::move(aModPaths), aRunAtNormalPriority)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aResolver](ModulesMapResult&& aResult) {
|
||||
aResolver(Some(ModulesMapResult(std::move(aResult))));
|
||||
},
|
||||
[aResolver](nsresult aRv) { aResolver(Nothing()); });
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL(this, "Unsupported on this platform");
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext(
|
||||
BrowsingContext::IPCInitializer&& aInit) {
|
||||
RefPtr<CanonicalBrowsingContext> parent;
|
||||
|
|
|
@ -1209,10 +1209,6 @@ class ContentParent final
|
|||
mozilla::ipc::IPCResult RecvNotifyMediaAudibleChanged(
|
||||
BrowsingContext* aContext, bool aAudible);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority,
|
||||
GetModulesTrustResolver&& aResolver);
|
||||
|
||||
// Notify the ContentChild to enable the input event prioritization when
|
||||
// initializing.
|
||||
void MaybeEnableRemoteInputEventQueue();
|
||||
|
|
|
@ -103,9 +103,6 @@ using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
|
|||
using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
|
||||
using mozilla::Telemetry::DynamicScalarDefinition from "mozilla/TelemetryComms.h";
|
||||
using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
|
||||
using moveonly mozilla::UntrustedModulesData from "mozilla/UntrustedModulesData.h";
|
||||
using moveonly mozilla::ModulePaths from "mozilla/UntrustedModulesData.h";
|
||||
using moveonly mozilla::ModulesMapResult from "mozilla/UntrustedModulesData.h";
|
||||
using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
|
||||
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
|
||||
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
|
||||
|
@ -478,12 +475,6 @@ child:
|
|||
FileDescriptor? DMDFile);
|
||||
async RequestPerformanceMetrics(nsID aID);
|
||||
|
||||
/**
|
||||
* Used by third-party modules telemetry (aka "untrusted modules" telemetry)
|
||||
* to pull data from content processes.
|
||||
*/
|
||||
async GetUntrustedModulesData() returns (UntrustedModulesData? data);
|
||||
|
||||
/**
|
||||
* Communication between the PuppetBidiKeyboard and the actual
|
||||
* BidiKeyboard hosted by the parent
|
||||
|
@ -1487,15 +1478,6 @@ parent:
|
|||
*/
|
||||
async NotifyMediaAudibleChanged(BrowsingContext aContext, bool aAudible);
|
||||
|
||||
/**
|
||||
* Due to sandboxing, a child process's UntrustedModulesProcessor cannot
|
||||
* obtain enough information about a DLL file to determine its
|
||||
* trustworthiness. This API asks the chrome process to perform that
|
||||
* evaluation.
|
||||
*/
|
||||
async GetModulesTrust(ModulePaths aModPaths, bool aRunAtNormalPriority)
|
||||
returns (ModulesMapResult? modMapResult);
|
||||
|
||||
both:
|
||||
async ScriptError(nsString message, nsString sourceName, nsString sourceLine,
|
||||
uint32_t lineNumber, uint32_t colNumber, uint32_t flags,
|
||||
|
|
|
@ -12,9 +12,6 @@ include protocol PRemoteDecoderManager;
|
|||
include protocol PVideoBridge;
|
||||
|
||||
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
||||
using moveonly mozilla::UntrustedModulesData from "mozilla/UntrustedModulesData.h";
|
||||
using moveonly mozilla::ModulePaths from "mozilla/UntrustedModulesData.h";
|
||||
using moveonly mozilla::ModulesMapResult from "mozilla/UntrustedModulesData.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -46,8 +43,6 @@ parent:
|
|||
|
||||
async InitVideoBridge(Endpoint<PVideoBridgeChild> endpoint);
|
||||
|
||||
async GetUntrustedModulesData() returns (UntrustedModulesData? data);
|
||||
|
||||
child:
|
||||
|
||||
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
|
||||
|
@ -55,8 +50,6 @@ child:
|
|||
async AddMemoryReport(MemoryReport aReport);
|
||||
async FinishMemoryReport(uint32_t aGeneration);
|
||||
|
||||
async GetModulesTrust(ModulePaths aModPaths, bool aRunAtNormalPriority)
|
||||
returns (ModulesMapResult? modMapResult);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
# include "mozilla/SandboxBrokerPolicyFactory.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/WinDllServices.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
# include "ProfilerParent.h"
|
||||
#endif
|
||||
|
@ -107,24 +103,6 @@ mozilla::ipc::IPCResult RDDChild::RecvFinishMemoryReport(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RDDChild::RecvGetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority,
|
||||
GetModulesTrustResolver&& aResolver) {
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->GetModulesTrust(std::move(aModPaths), aRunAtNormalPriority)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aResolver](ModulesMapResult&& aResult) {
|
||||
aResolver(Some(ModulesMapResult(std::move(aResult))));
|
||||
},
|
||||
[aResolver](nsresult aRv) { aResolver(Nothing()); });
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL(this, "Unsupported on this platform");
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
void RDDChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
if (aWhy == AbnormalShutdown) {
|
||||
GenerateCrashReport(OtherPid());
|
||||
|
|
|
@ -43,9 +43,6 @@ class RDDChild final : public PRDDChild,
|
|||
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
|
||||
mozilla::ipc::IPCResult RecvGetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority,
|
||||
GetModulesTrustResolver&& aResolver);
|
||||
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#if defined(XP_WIN)
|
||||
# include <process.h>
|
||||
# include <dwrite.h>
|
||||
# include "mozilla/WinDllServices.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
@ -89,11 +88,6 @@ bool RDDParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
|
|||
gfxVars::Initialize();
|
||||
|
||||
mozilla::ipc::SetThisProcessName("RDD Process");
|
||||
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->StartUntrustedModulesProcessor();
|
||||
#endif // defined(XP_WIN)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -203,22 +197,6 @@ mozilla::ipc::IPCResult RDDParent::RecvRequestMemoryReport(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RDDParent::RecvGetUntrustedModulesData(
|
||||
GetUntrustedModulesDataResolver&& aResolver) {
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->GetUntrustedModulesData()->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aResolver](Maybe<UntrustedModulesData>&& aData) {
|
||||
aResolver(std::move(aData));
|
||||
},
|
||||
[aResolver](nsresult aReason) { aResolver(Nothing()); });
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL(this, "Unsupported on this platform");
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RDDParent::RecvPreferenceUpdate(const Pref& aPref) {
|
||||
Preferences::SetPreference(aPref);
|
||||
return IPC_OK();
|
||||
|
@ -236,11 +214,6 @@ void RDDParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|||
ProcessChild::QuickExit();
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->DisableFull();
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->Shutdown();
|
||||
|
|
|
@ -38,8 +38,6 @@ class RDDParent final : public PRDDParent {
|
|||
const uint32_t& generation, const bool& anonymize,
|
||||
const bool& minimizeMemoryUsage,
|
||||
const Maybe<ipc::FileDescriptor>& DMDFile);
|
||||
mozilla::ipc::IPCResult RecvGetUntrustedModulesData(
|
||||
GetUntrustedModulesDataResolver&& aResolver);
|
||||
mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref);
|
||||
mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref);
|
||||
|
||||
|
|
|
@ -92,15 +92,6 @@ class NS_NO_VTABLE LoaderAPI {
|
|||
* backing it.
|
||||
*/
|
||||
virtual AllocatedUnicodeString GetSectionName(void* aSectionAddr) = 0;
|
||||
|
||||
using InitDllBlocklistOOPFnPtr =
|
||||
LauncherVoidResultWithLineInfo (*)(const wchar_t*, HANDLE);
|
||||
|
||||
/**
|
||||
* Return a pointer to the cross-process DLL Blocklist Init function.
|
||||
* Used by sandboxBroker::LaunchApp.
|
||||
*/
|
||||
virtual InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() = 0;
|
||||
};
|
||||
|
||||
} // namespace nt
|
||||
|
|
|
@ -28,8 +28,7 @@ nt::LoaderAPI* ModuleLoadFrame::sLoaderAPI;
|
|||
using GetNtLoaderAPIFn = decltype(&mozilla::GetNtLoaderAPI);
|
||||
|
||||
/* static */
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr ModuleLoadFrame::StaticInit(
|
||||
nt::LoaderObserver* aNewObserver) {
|
||||
void ModuleLoadFrame::StaticInit(nt::LoaderObserver* aNewObserver) {
|
||||
const auto pGetNtLoaderAPI = reinterpret_cast<GetNtLoaderAPIFn>(
|
||||
::GetProcAddress(::GetModuleHandleW(nullptr), "GetNtLoaderAPI"));
|
||||
if (!pGetNtLoaderAPI) {
|
||||
|
@ -37,12 +36,10 @@ nt::LoaderAPI::InitDllBlocklistOOPFnPtr ModuleLoadFrame::StaticInit(
|
|||
// the launcher process blocklist.
|
||||
gFallbackLoaderAPI.SetObserver(aNewObserver);
|
||||
sLoaderAPI = &gFallbackLoaderAPI;
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
sLoaderAPI = pGetNtLoaderAPI(aNewObserver);
|
||||
MOZ_ASSERT(sLoaderAPI);
|
||||
return sLoaderAPI->GetDllBlocklistInitFn();
|
||||
}
|
||||
|
||||
ModuleLoadFrame::ModuleLoadFrame(PCUNICODE_STRING aRequestedDllName)
|
||||
|
|
|
@ -25,8 +25,7 @@ class MOZ_RAII ModuleLoadFrame final {
|
|||
ModuleLoadFrame& operator=(const ModuleLoadFrame&) = delete;
|
||||
ModuleLoadFrame& operator=(ModuleLoadFrame&&) = delete;
|
||||
|
||||
static nt::LoaderAPI::InitDllBlocklistOOPFnPtr StaticInit(
|
||||
nt::LoaderObserver* aNewObserver);
|
||||
static void StaticInit(nt::LoaderObserver* aNewObserver);
|
||||
|
||||
private:
|
||||
bool mAlreadyLoaded;
|
||||
|
|
|
@ -588,7 +588,6 @@ static WindowsDllInterceptor Kernel32Intercept;
|
|||
static void GetNativeNtBlockSetWriter();
|
||||
|
||||
static glue::LoaderObserver gMozglueLoaderObserver;
|
||||
static nt::LoaderAPI::InitDllBlocklistOOPFnPtr gInitDllBlocklistOOPFnPtr;
|
||||
|
||||
MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags) {
|
||||
if (sBlocklistInitAttempted) {
|
||||
|
@ -598,8 +597,7 @@ MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags) {
|
|||
|
||||
sInitFlags = aInitFlags;
|
||||
|
||||
gInitDllBlocklistOOPFnPtr =
|
||||
glue::ModuleLoadFrame::StaticInit(&gMozglueLoaderObserver);
|
||||
glue::ModuleLoadFrame::StaticInit(&gMozglueLoaderObserver);
|
||||
|
||||
#ifdef _M_AMD64
|
||||
if (!IsWin8OrLater()) {
|
||||
|
@ -755,7 +753,6 @@ MFBT_API void DllBlocklist_SetFullDllServices(
|
|||
glue::AutoExclusiveLock lock(gDllServicesLock);
|
||||
if (aSvc) {
|
||||
aSvc->SetAuthenticodeImpl(GetAuthenticode());
|
||||
aSvc->SetInitDllBlocklistOOPFnPtr(gInitDllBlocklistOOPFnPtr);
|
||||
gMozglueLoaderObserver.Forward(aSvc);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,6 @@ enum DllBlocklistInitFlags {
|
|||
eDllBlocklistInitFlagWasBootstrapped = 2
|
||||
};
|
||||
|
||||
// Only available from within firefox.exe
|
||||
# if !defined(IMPL_MFBT) && !defined(MOZILLA_INTERNAL_API)
|
||||
extern uint32_t gBlocklistInitFlags;
|
||||
# endif // !defined(IMPL_MFBT) && !defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
MFBT_API void DllBlocklist_Initialize(
|
||||
uint32_t aInitFlags = eDllBlocklistInitFlagDefault);
|
||||
MFBT_API void DllBlocklist_WriteNotes(CrashReporter::AnnotationWriter& aWriter);
|
||||
|
|
|
@ -10,12 +10,10 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Authenticode.h"
|
||||
#include "mozilla/LoaderAPIInterfaces.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/WindowsDllBlocklist.h"
|
||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
|
@ -59,17 +57,6 @@ class DllServicesBase : public Authenticode {
|
|||
mAuthenticode = aAuthenticode;
|
||||
}
|
||||
|
||||
void SetInitDllBlocklistOOPFnPtr(
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr aPtr) {
|
||||
mInitDllBlocklistOOPFnPtr = aPtr;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
LauncherVoidResultWithLineInfo InitDllBlocklistOOP(Args&&... aArgs) {
|
||||
MOZ_RELEASE_ASSERT(mInitDllBlocklistOOPFnPtr);
|
||||
return mInitDllBlocklistOOPFnPtr(std::forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -90,7 +77,7 @@ class DllServicesBase : public Authenticode {
|
|||
return mAuthenticode->GetBinaryOrgName(aFilePath, aFlags);
|
||||
}
|
||||
|
||||
virtual void DisableFull() { DllBlocklist_SetFullDllServices(nullptr); }
|
||||
void DisableFull() { DllBlocklist_SetFullDllServices(nullptr); }
|
||||
|
||||
DllServicesBase(const DllServicesBase&) = delete;
|
||||
DllServicesBase(DllServicesBase&&) = delete;
|
||||
|
@ -98,8 +85,7 @@ class DllServicesBase : public Authenticode {
|
|||
DllServicesBase& operator=(DllServicesBase&&) = delete;
|
||||
|
||||
protected:
|
||||
DllServicesBase()
|
||||
: mAuthenticode(nullptr), mInitDllBlocklistOOPFnPtr(nullptr) {}
|
||||
DllServicesBase() : mAuthenticode(nullptr) {}
|
||||
|
||||
virtual ~DllServicesBase() = default;
|
||||
|
||||
|
@ -108,7 +94,6 @@ class DllServicesBase : public Authenticode {
|
|||
|
||||
private:
|
||||
Authenticode* mAuthenticode;
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr mInitDllBlocklistOOPFnPtr;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -67,12 +67,6 @@ nt::AllocatedUnicodeString FallbackLoaderAPI::GetSectionName(
|
|||
return nt::AllocatedUnicodeString(&buf.mSectionFileName);
|
||||
}
|
||||
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr
|
||||
FallbackLoaderAPI::GetDllBlocklistInitFn() {
|
||||
MOZ_ASSERT_UNREACHABLE("This should not be called so soon!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FallbackLoaderAPI::SetObserver(nt::LoaderObserver* aLoaderObserver) {
|
||||
mLoaderObserver = aLoaderObserver;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS FallbackLoaderAPI final
|
|||
void NotifyEndDllLoad(void* aContext, NTSTATUS aLoadNtStatus,
|
||||
ModuleLoadInfo&& aModuleLoadInfo) final;
|
||||
nt::AllocatedUnicodeString GetSectionName(void* aSectionAddr) final;
|
||||
nt::LoaderAPI::InitDllBlocklistOOPFnPtr GetDllBlocklistInitFn() final;
|
||||
|
||||
void SetObserver(nt::LoaderObserver* aLoaderObserver);
|
||||
|
||||
|
|
|
@ -358,8 +358,7 @@ GENERATED_BLOCKLIST_FILES = [
|
|||
# Child is not used by anything at the moment, so we'll just leave this
|
||||
# descriptor commented out for now.
|
||||
# BlocklistDescriptor('Child', ['ALL_PROCESSES', 'CHILD_PROCESSES']),
|
||||
BlocklistDescriptor('Launcher', ALL_DEFINITION_LISTS, flagspec={
|
||||
'CHILD_PROCESSES': {CHILD_PROCESSES_ONLY}}),
|
||||
BlocklistDescriptor('Launcher', ['ALL_PROCESSES', 'BROWSER_PROCESS']),
|
||||
BlocklistDescriptor('Legacy', ALL_DEFINITION_LISTS, flagspec={
|
||||
'CHILD_PROCESSES': {CHILD_PROCESSES_ONLY}}),
|
||||
# Roughed-in for the moment; we'll enable this in bug 1238735
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "mozilla/StaticPrefs_security.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/WinDllServices.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -334,22 +333,6 @@ bool SandboxBroker::LaunchApp(const wchar_t* aPath, const wchar_t* aArguments,
|
|||
}
|
||||
}
|
||||
|
||||
if (XRE_GetChildProcBinPathType(aProcessType) == BinPathType::Self) {
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
LauncherVoidResultWithLineInfo blocklistInitOk =
|
||||
dllSvc->InitDllBlocklistOOP(aPath, targetInfo.hProcess);
|
||||
if (blocklistInitOk.isErr()) {
|
||||
LOG_E("InitDllBlocklistOOP failed at %s:%d with HRESULT 0x%08lX",
|
||||
blocklistInitOk.unwrapErr().mFile,
|
||||
blocklistInitOk.unwrapErr().mLine,
|
||||
blocklistInitOk.unwrapErr().mError.AsHResult());
|
||||
TerminateProcess(targetInfo.hProcess, 1);
|
||||
CloseHandle(targetInfo.hThread);
|
||||
CloseHandle(targetInfo.hProcess);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The sandboxed process is started in a suspended state, resume it now that
|
||||
// we've set things up.
|
||||
ResumeThread(targetInfo.hThread);
|
||||
|
|
|
@ -7,15 +7,10 @@
|
|||
#include "UntrustedModules.h"
|
||||
|
||||
#include "core/TelemetryCommon.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/RDDChild.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
#include "mozilla/UntrustedModulesProcessor.h"
|
||||
#include "mozilla/WinDllServices.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsLocalFile.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -276,8 +271,15 @@ static bool SerializeEvent(JSContext* aCx, JS::MutableHandleValue aElement,
|
|||
return false;
|
||||
}
|
||||
|
||||
nsAutoString resolvedDllPath;
|
||||
const nsCOMPtr<nsIFile>& resolvedDllName = aEvent.mModule->mResolvedDllName;
|
||||
if (!resolvedDllName ||
|
||||
NS_FAILED(resolvedDllName->GetPath(resolvedDllPath))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t index;
|
||||
if (!aModuleIndices.Get(aEvent.mModule->mResolvedNtName, &index)) {
|
||||
if (!aModuleIndices.Get(resolvedDllPath, &index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -366,16 +368,21 @@ static nsresult GetPerProcObject(JSContext* aCx, const IndexMap& aModuleIndices,
|
|||
/**
|
||||
* Converts a UntrustedModulesData to a JS object.
|
||||
*
|
||||
* @param aData [in] The source objects to convert.
|
||||
* @param aData [in] The source object to convert.
|
||||
* @param aCx [in] The JS context.
|
||||
* @param aRet [out] This gets assigned to the newly created object.
|
||||
* @return nsresult
|
||||
*/
|
||||
static nsresult GetUntrustedModuleLoadEventsJSValue(
|
||||
const Vector<UntrustedModulesData>& aData, JSContext* aCx,
|
||||
const UntrustedModulesData& aData, JSContext* aCx,
|
||||
JS::MutableHandleValue aRet) {
|
||||
if (aData.empty()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (aData.mEvents.empty()) {
|
||||
aRet.setNull();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aData.mModules.Count() > kMaxModulesArrayLen) {
|
||||
return NS_ERROR_CANNOT_CONVERT_DATA;
|
||||
}
|
||||
|
||||
JS::RootedObject mainObj(aCx, JS_NewPlainObject(aCx));
|
||||
|
@ -403,49 +410,43 @@ static nsresult GetUntrustedModuleLoadEventsJSValue(
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
for (auto&& procData : aData) {
|
||||
// Serialize each entry in the modules hashtable out to the "modules" array
|
||||
// and store the indices in |indexMap|
|
||||
for (auto iter = procData.mModules.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto addPtr = indexMap.LookupForAdd(iter.Key());
|
||||
if (!addPtr) {
|
||||
addPtr.OrInsert([curModulesArrayIdx]() { return curModulesArrayIdx; });
|
||||
// Serialize each entry in the modules hashtable out to the "modules" array
|
||||
// and store the indices in |indexMap|
|
||||
for (auto iter = aData.mModules.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto addPtr = indexMap.LookupForAdd(iter.Key());
|
||||
if (!addPtr) {
|
||||
addPtr.OrInsert([curModulesArrayIdx]() { return curModulesArrayIdx; });
|
||||
|
||||
JS::RootedValue jsModule(aCx);
|
||||
if (!SerializeModule(aCx, &jsModule, iter.Data()) ||
|
||||
!JS_DefineElement(aCx, modulesArray, curModulesArrayIdx, jsModule,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
++curModulesArrayIdx;
|
||||
JS::RootedValue jsModule(aCx);
|
||||
if (!SerializeModule(aCx, &jsModule, iter.Data()) ||
|
||||
!JS_DefineElement(aCx, modulesArray, curModulesArrayIdx, jsModule,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (curModulesArrayIdx >= kMaxModulesArrayLen) {
|
||||
return NS_ERROR_CANNOT_CONVERT_DATA;
|
||||
++curModulesArrayIdx;
|
||||
}
|
||||
}
|
||||
|
||||
JS::RootedObject perProcObj(aCx, JS_NewPlainObject(aCx));
|
||||
if (!perProcObj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JS::RootedObject perProcObj(aCx, JS_NewPlainObject(aCx));
|
||||
if (!perProcObj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = GetPerProcObject(aCx, indexMap, procData, &perProcObj);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = GetPerProcObject(aCx, indexMap, aData, &perProcObj);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString strPid;
|
||||
strPid.AppendLiteral("0x");
|
||||
strPid.AppendInt(static_cast<uint32_t>(procData.mPid), 16);
|
||||
nsAutoCString strPid;
|
||||
strPid.AppendLiteral("0x");
|
||||
strPid.AppendInt(static_cast<uint32_t>(aData.mPid), 16);
|
||||
|
||||
JS::RootedValue jsPerProcObjValue(aCx);
|
||||
jsPerProcObjValue.setObject(*perProcObj);
|
||||
if (!JS_DefineProperty(aCx, perProcObjContainer, strPid.get(),
|
||||
jsPerProcObjValue, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JS::RootedValue jsPerProcObjValue(aCx);
|
||||
jsPerProcObjValue.setObject(*perProcObj);
|
||||
if (!JS_DefineProperty(aCx, perProcObjContainer, strPid.get(),
|
||||
jsPerProcObjValue, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::RootedValue jsModulesArrayValue(aCx);
|
||||
|
@ -466,7 +467,7 @@ static nsresult GetUntrustedModuleLoadEventsJSValue(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void Serialize(Vector<UntrustedModulesData>&& aData,
|
||||
static void Serialize(Maybe<UntrustedModulesData>&& aData,
|
||||
RefPtr<dom::Promise>&& aPromise) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -476,7 +477,7 @@ static void Serialize(Vector<UntrustedModulesData>&& aData,
|
|||
return;
|
||||
}
|
||||
|
||||
if (aData.empty()) {
|
||||
if (aData.isNothing()) {
|
||||
aPromise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
@ -484,7 +485,7 @@ static void Serialize(Vector<UntrustedModulesData>&& aData,
|
|||
JSContext* cx = jsapi.cx();
|
||||
JS::RootedValue jsval(cx);
|
||||
|
||||
nsresult rv = GetUntrustedModuleLoadEventsJSValue(aData, cx, &jsval);
|
||||
nsresult rv = GetUntrustedModuleLoadEventsJSValue(aData.ref(), cx, &jsval);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aPromise->MaybeReject(rv);
|
||||
return;
|
||||
|
@ -493,118 +494,6 @@ static void Serialize(Vector<UntrustedModulesData>&& aData,
|
|||
aPromise->MaybeResolve(jsval);
|
||||
}
|
||||
|
||||
using UntrustedModulesIpcPromise =
|
||||
MozPromise<Maybe<UntrustedModulesData>, ipc::ResponseRejectReason, true>;
|
||||
|
||||
using MultiGetUntrustedModulesPromise =
|
||||
MozPromise<Vector<UntrustedModulesData>, nsresult, true>;
|
||||
|
||||
class MOZ_HEAP_CLASS MultiGetUntrustedModulesData final {
|
||||
public:
|
||||
MultiGetUntrustedModulesData()
|
||||
: mPromise(new MultiGetUntrustedModulesPromise::Private(__func__)),
|
||||
mNumPending(0) {}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MultiGetUntrustedModulesData)
|
||||
|
||||
RefPtr<MultiGetUntrustedModulesPromise> GetUntrustedModuleLoadEvents();
|
||||
|
||||
MultiGetUntrustedModulesData(const MultiGetUntrustedModulesData&) = delete;
|
||||
MultiGetUntrustedModulesData(MultiGetUntrustedModulesData&&) = delete;
|
||||
MultiGetUntrustedModulesData& operator=(const MultiGetUntrustedModulesData&) =
|
||||
delete;
|
||||
MultiGetUntrustedModulesData& operator=(MultiGetUntrustedModulesData&&) =
|
||||
delete;
|
||||
|
||||
private:
|
||||
~MultiGetUntrustedModulesData() = default;
|
||||
|
||||
void AddPending(RefPtr<UntrustedModulesPromise>&& aNewPending) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
++mNumPending;
|
||||
|
||||
RefPtr<MultiGetUntrustedModulesData> self(this);
|
||||
aNewPending->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self](Maybe<UntrustedModulesData>&& aResult) {
|
||||
self->OnCompletion(std::move(aResult));
|
||||
},
|
||||
[self](nsresult aReason) { self->OnCompletion(); });
|
||||
}
|
||||
|
||||
void AddPending(RefPtr<UntrustedModulesIpcPromise>&& aNewPending) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
++mNumPending;
|
||||
|
||||
RefPtr<MultiGetUntrustedModulesData> self(this);
|
||||
aNewPending->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self](Maybe<UntrustedModulesData>&& aResult) {
|
||||
self->OnCompletion(std::move(aResult));
|
||||
},
|
||||
[self](ipc::ResponseRejectReason&& aReason) { self->OnCompletion(); });
|
||||
}
|
||||
|
||||
void OnCompletion() {
|
||||
MOZ_ASSERT(NS_IsMainThread() && mNumPending > 0);
|
||||
|
||||
--mNumPending;
|
||||
if (mNumPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mResults.empty()) {
|
||||
mPromise->Reject(NS_ERROR_NOT_AVAILABLE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mPromise->Resolve(std::move(mResults), __func__);
|
||||
}
|
||||
|
||||
void OnCompletion(Maybe<UntrustedModulesData>&& aResult) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aResult.isSome()) {
|
||||
Unused << mResults.emplaceBack(std::move(aResult.ref()));
|
||||
}
|
||||
|
||||
OnCompletion();
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<MultiGetUntrustedModulesPromise::Private> mPromise;
|
||||
Vector<UntrustedModulesData> mResults;
|
||||
size_t mNumPending;
|
||||
};
|
||||
|
||||
RefPtr<MultiGetUntrustedModulesPromise>
|
||||
MultiGetUntrustedModulesData::GetUntrustedModuleLoadEvents() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
|
||||
|
||||
// Parent process
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
AddPending(dllSvc->GetUntrustedModulesData());
|
||||
|
||||
// Child processes
|
||||
nsTArray<dom::ContentParent*> contentParents;
|
||||
dom::ContentParent::GetAll(contentParents);
|
||||
for (auto&& contentParent : contentParents) {
|
||||
AddPending(contentParent->SendGetUntrustedModulesData());
|
||||
}
|
||||
|
||||
if (RDDProcessManager* rddMgr = RDDProcessManager::Get()) {
|
||||
if (RDDChild* rddChild = rddMgr->GetRDDChild()) {
|
||||
AddPending(rddChild->SendGetUntrustedModulesData());
|
||||
}
|
||||
}
|
||||
|
||||
Unused << mResults.reserve(mNumPending);
|
||||
|
||||
return mPromise;
|
||||
}
|
||||
|
||||
nsresult GetUntrustedModuleLoadEvents(JSContext* cx, dom::Promise** aPromise) {
|
||||
// Create a promise using global context.
|
||||
nsIGlobalObject* global = xpc::CurrentNativeGlobal(cx);
|
||||
|
@ -618,12 +507,10 @@ nsresult GetUntrustedModuleLoadEvents(JSContext* cx, dom::Promise** aPromise) {
|
|||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
RefPtr<MultiGetUntrustedModulesData> multi(
|
||||
new MultiGetUntrustedModulesData());
|
||||
|
||||
multi->GetUntrustedModuleLoadEvents()->Then(
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
dllSvc->GetUntrustedModulesData()->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[promise](Vector<UntrustedModulesData>&& aData) mutable {
|
||||
[promise](Maybe<UntrustedModulesData>&& aData) mutable {
|
||||
Serialize(std::move(aData), std::move(promise));
|
||||
},
|
||||
[promise](nsresult aRv) { promise->MaybeReject(aRv); });
|
||||
|
|
|
@ -91,8 +91,6 @@ bool ModuleEvaluator::ResolveKnownFolder(REFKNOWNFOLDERID aFolderId,
|
|||
|
||||
ModuleEvaluator::ModuleEvaluator()
|
||||
: mKeyboardLayoutDlls(GetKeyboardLayoutDlls()) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
#if defined(_M_IX86)
|
||||
// We want to resolve to SYSWOW64 when applicable
|
||||
REFKNOWNFOLDERID systemFolderId = FOLDERID_SystemX86;
|
||||
|
@ -157,8 +155,6 @@ ModuleEvaluator::operator bool() const {
|
|||
|
||||
Maybe<ModuleTrustFlags> ModuleEvaluator::GetTrust(
|
||||
const ModuleRecord& aModuleRecord) const {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
// We start by checking authenticode signatures, as the presence of any
|
||||
// signature will produce an immediate pass/fail.
|
||||
if (aModuleRecord.mVendorInfo.isSome() &&
|
||||
|
@ -179,11 +175,7 @@ Maybe<ModuleTrustFlags> ModuleEvaluator::GetTrust(
|
|||
}
|
||||
}
|
||||
|
||||
const nsCOMPtr<nsIFile>& dllFile = aModuleRecord.mResolvedDosName;
|
||||
MOZ_ASSERT(!!dllFile);
|
||||
if (!dllFile) {
|
||||
return Nothing();
|
||||
}
|
||||
const nsCOMPtr<nsIFile>& dllFile = aModuleRecord.mResolvedDllName;
|
||||
|
||||
nsAutoString dllLeafLower;
|
||||
if (NS_FAILED(dllFile->GetLeafName(dllLeafLower))) {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "mozilla/WinDllServices.h"
|
||||
#include "ModuleEvaluator.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
@ -74,39 +73,23 @@ static Maybe<double> QPCLoadDurationToMilliseconds(
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
ModuleRecord::ModuleRecord() : mTrustFlags(ModuleTrustFlags::None) {}
|
||||
|
||||
ModuleRecord::ModuleRecord(const nsAString& aResolvedNtPath)
|
||||
: mResolvedNtName(aResolvedNtPath), mTrustFlags(ModuleTrustFlags::None) {
|
||||
if (aResolvedNtPath.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
nsAutoString resolvedDosPath;
|
||||
if (!NtPathToDosPath(aResolvedNtPath, resolvedDosPath)) {
|
||||
#if defined(DEBUG)
|
||||
nsAutoCString msg;
|
||||
msg.AppendLiteral("NtPathToDosPath failed for path \"");
|
||||
msg.Append(NS_ConvertUTF16toUTF8(aResolvedNtPath));
|
||||
msg.AppendLiteral("\"");
|
||||
NS_WARNING(msg.get());
|
||||
#endif // defined(DEBUG)
|
||||
ModuleRecord::ModuleRecord(const nsAString& aResolvedPath)
|
||||
: mTrustFlags(ModuleTrustFlags::None) {
|
||||
if (aResolvedPath.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
NS_NewLocalFile(resolvedDosPath, false, getter_AddRefs(mResolvedDosName));
|
||||
if (NS_FAILED(rv) || !mResolvedDosName) {
|
||||
NS_NewLocalFile(aResolvedPath, false, getter_AddRefs(mResolvedDllName));
|
||||
if (NS_FAILED(rv) || !mResolvedDllName) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetVersionAndVendorInfo(resolvedDosPath);
|
||||
GetVersionAndVendorInfo(aResolvedPath);
|
||||
|
||||
// Now sanitize the resolved DLL name. If we cannot sanitize this then this
|
||||
// record must not be considered valid.
|
||||
nsAutoString strSanitizedPath(resolvedDosPath);
|
||||
nsAutoString strSanitizedPath(aResolvedPath);
|
||||
if (!widget::WinUtils::PreparePathForTelemetry(strSanitizedPath)) {
|
||||
return;
|
||||
}
|
||||
|
@ -143,12 +126,12 @@ void ModuleRecord::GetVersionAndVendorInfo(const nsAString& aPath) {
|
|||
}
|
||||
|
||||
bool ModuleRecord::IsXUL() const {
|
||||
if (!mResolvedDosName) {
|
||||
if (!mResolvedDllName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString leafName;
|
||||
nsresult rv = mResolvedDosName->GetLeafName(leafName);
|
||||
nsresult rv = mResolvedDllName->GetLeafName(leafName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -161,7 +144,7 @@ int32_t ModuleRecord::GetScoreThreshold() const {
|
|||
// Check whether we are running as an xpcshell test.
|
||||
if (MOZ_UNLIKELY(mozilla::EnvHasValue("XPCSHELL_TEST_PROFILE_DIR"))) {
|
||||
nsAutoString dllLeaf;
|
||||
if (NS_SUCCEEDED(mResolvedDosName->GetLeafName(dllLeaf))) {
|
||||
if (NS_SUCCEEDED(mResolvedDllName->GetLeafName(dllLeaf))) {
|
||||
// During xpcshell tests, this DLL is hard-coded to pass through all
|
||||
// criteria checks and still result in "untrusted" status, so it shows up
|
||||
// in the untrusted modules ping for the test to examine.
|
||||
|
@ -197,9 +180,6 @@ bool ModuleRecord::IsTrusted() const {
|
|||
return score >= GetScoreThreshold();
|
||||
}
|
||||
|
||||
ProcessedModuleLoadEvent::ProcessedModuleLoadEvent()
|
||||
: mProcessUptimeMS(0ULL), mThreadId(0UL), mBaseAddress(0U) {}
|
||||
|
||||
ProcessedModuleLoadEvent::ProcessedModuleLoadEvent(
|
||||
glue::EnhancedModuleLoadInfo&& aModLoadInfo,
|
||||
RefPtr<ModuleRecord>&& aModuleRecord)
|
||||
|
@ -284,7 +264,7 @@ uint64_t ProcessedModuleLoadEvent::QPCTimeStampToProcessUptimeMilliseconds(
|
|||
}
|
||||
|
||||
bool ProcessedModuleLoadEvent::IsXULLoad() const {
|
||||
if (!mModule || !mLoadDurationMS) {
|
||||
if (!mModule || !mLoadDurationMS || !IsTrusted()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,25 +7,18 @@
|
|||
#ifndef mozilla_UntrustedModulesData_h
|
||||
#define mozilla_UntrustedModulesData_h
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
# include "ipc/IPCMessageUtils.h"
|
||||
# include "mozilla/CombinedStacks.h"
|
||||
# include "mozilla/DebugOnly.h"
|
||||
# include "mozilla/Maybe.h"
|
||||
# include "mozilla/RefPtr.h"
|
||||
# include "mozilla/TypedEnumBits.h"
|
||||
# include "mozilla/Unused.h"
|
||||
# include "mozilla/Variant.h"
|
||||
# include "mozilla/Vector.h"
|
||||
# include "mozilla/WinHeaderOnlyUtils.h"
|
||||
# include "nsCOMPtr.h"
|
||||
# include "nsHashKeys.h"
|
||||
# include "nsIFile.h"
|
||||
# include "nsISupportsImpl.h"
|
||||
# include "nsRefPtrHashtable.h"
|
||||
# include "nsString.h"
|
||||
# include "nsXULAppAPI.h"
|
||||
#include "mozilla/CombinedStacks.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace glue {
|
||||
|
@ -50,31 +43,26 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ModuleTrustFlags);
|
|||
class VendorInfo final {
|
||||
public:
|
||||
enum class Source : uint32_t {
|
||||
None,
|
||||
Signature,
|
||||
VersionInfo,
|
||||
};
|
||||
|
||||
VendorInfo() : mSource(Source::None) {}
|
||||
VendorInfo(const Source aSource, const nsAString& aVendor)
|
||||
: mSource(aSource), mVendor(aVendor) {
|
||||
MOZ_ASSERT(aSource != Source::None && !aVendor.IsEmpty());
|
||||
MOZ_ASSERT(!aVendor.IsEmpty());
|
||||
}
|
||||
|
||||
Source mSource;
|
||||
nsString mVendor;
|
||||
};
|
||||
|
||||
class ModulesMap;
|
||||
|
||||
class ModuleRecord final {
|
||||
public:
|
||||
explicit ModuleRecord(const nsAString& aResolvedNtPath);
|
||||
explicit ModuleRecord(const nsAString& aResolvedPath);
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ModuleRecord)
|
||||
|
||||
nsString mResolvedNtName;
|
||||
nsCOMPtr<nsIFile> mResolvedDosName;
|
||||
nsCOMPtr<nsIFile> mResolvedDllName;
|
||||
nsString mSanitizedDllName;
|
||||
Maybe<ModuleVersion> mVersion;
|
||||
Maybe<VendorInfo> mVendorInfo;
|
||||
|
@ -91,41 +79,13 @@ class ModuleRecord final {
|
|||
ModuleRecord& operator=(ModuleRecord&&) = delete;
|
||||
|
||||
private:
|
||||
ModuleRecord();
|
||||
~ModuleRecord() = default;
|
||||
void GetVersionAndVendorInfo(const nsAString& aPath);
|
||||
int32_t GetScoreThreshold() const;
|
||||
|
||||
friend struct ::IPC::ParamTraits<ModulesMap>;
|
||||
};
|
||||
|
||||
/**
|
||||
* This type holds module path data using one of two internal representations.
|
||||
* It may be created from either a nsTHashtable or a Vector, and may be
|
||||
* serialized from either representation into a common format over the wire.
|
||||
* Deserialization always uses the Vector representation.
|
||||
*/
|
||||
struct ModulePaths final {
|
||||
using SetType = nsTHashtable<nsStringCaseInsensitiveHashKey>;
|
||||
using VecType = Vector<nsString>;
|
||||
|
||||
Variant<SetType, VecType> mModuleNtPaths;
|
||||
|
||||
template <typename T>
|
||||
explicit ModulePaths(T&& aPaths)
|
||||
: mModuleNtPaths(AsVariant(std::forward<T>(aPaths))) {}
|
||||
|
||||
ModulePaths() : mModuleNtPaths(VecType()) {}
|
||||
|
||||
ModulePaths(const ModulePaths& aOther) = delete;
|
||||
ModulePaths(ModulePaths&& aOther) = default;
|
||||
ModulePaths& operator=(const ModulePaths&) = delete;
|
||||
ModulePaths& operator=(ModulePaths&&) = default;
|
||||
};
|
||||
|
||||
class ProcessedModuleLoadEvent final {
|
||||
public:
|
||||
ProcessedModuleLoadEvent();
|
||||
ProcessedModuleLoadEvent(glue::EnhancedModuleLoadInfo&& aModLoadInfo,
|
||||
RefPtr<ModuleRecord>&& aModuleRecord);
|
||||
|
||||
|
@ -156,17 +116,10 @@ class ProcessedModuleLoadEvent final {
|
|||
const LARGE_INTEGER& aTimeStamp);
|
||||
};
|
||||
|
||||
// Declaring ModulesMap this way makes it much easier to forward declare than
|
||||
// if we had used |using| or |typedef|.
|
||||
class ModulesMap final
|
||||
: public nsRefPtrHashtable<nsStringCaseInsensitiveHashKey, ModuleRecord> {
|
||||
public:
|
||||
ModulesMap()
|
||||
: nsRefPtrHashtable<nsStringCaseInsensitiveHashKey, ModuleRecord>() {}
|
||||
};
|
||||
|
||||
class UntrustedModulesData final {
|
||||
public:
|
||||
using ModulesMap = nsRefPtrHashtable<nsStringHashKey, ModuleRecord>;
|
||||
|
||||
UntrustedModulesData()
|
||||
: mProcessType(XRE_GetProcessType()),
|
||||
mPid(::GetCurrentProcessId()),
|
||||
|
@ -201,403 +154,6 @@ class UntrustedModulesData final {
|
|||
uint32_t mTrustTestFailures;
|
||||
};
|
||||
|
||||
class ModulesMapResult final {
|
||||
public:
|
||||
ModulesMapResult() : mTrustTestFailures(0) {}
|
||||
|
||||
ModulesMapResult(const ModulesMapResult& aOther) = delete;
|
||||
ModulesMapResult(ModulesMapResult&& aOther) = default;
|
||||
ModulesMapResult& operator=(const ModulesMapResult& aOther) = delete;
|
||||
ModulesMapResult& operator=(ModulesMapResult&& aOther) = default;
|
||||
|
||||
ModulesMap mModules;
|
||||
uint32_t mTrustTestFailures;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ModuleVersion> {
|
||||
typedef mozilla::ModuleVersion paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt64(aParam.AsInteger());
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint64_t ver;
|
||||
if (!aMsg->ReadUInt64(aIter, &ver)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aResult = ver;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::VendorInfo> {
|
||||
typedef mozilla::VendorInfo paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mSource));
|
||||
WriteParam(aMsg, aParam.mVendor);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t source;
|
||||
if (!aMsg->ReadUInt32(aIter, &source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->mSource = static_cast<mozilla::VendorInfo::Source>(source);
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mVendor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ModuleRecord> {
|
||||
typedef mozilla::ModuleRecord paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mResolvedNtName);
|
||||
|
||||
nsAutoString resolvedDosName;
|
||||
if (aParam.mResolvedDosName) {
|
||||
mozilla::DebugOnly<nsresult> rv =
|
||||
aParam.mResolvedDosName->GetPath(resolvedDosName);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
WriteParam(aMsg, resolvedDosName);
|
||||
WriteParam(aMsg, aParam.mSanitizedDllName);
|
||||
WriteParam(aMsg, aParam.mVersion);
|
||||
WriteParam(aMsg, aParam.mVendorInfo);
|
||||
aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mTrustFlags));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mResolvedNtName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString resolvedDosName;
|
||||
if (!ReadParam(aMsg, aIter, &resolvedDosName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resolvedDosName.IsEmpty()) {
|
||||
aResult->mResolvedDosName = nullptr;
|
||||
} else if (NS_FAILED(NS_NewLocalFile(
|
||||
resolvedDosName, false,
|
||||
getter_AddRefs(aResult->mResolvedDosName)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mSanitizedDllName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mVersion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mVendorInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t trustFlags;
|
||||
if (!aMsg->ReadUInt32(aIter, &trustFlags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->mTrustFlags = static_cast<mozilla::ModuleTrustFlags>(trustFlags);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ModulesMap> {
|
||||
typedef mozilla::ModulesMap paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt32(aParam.Count());
|
||||
|
||||
for (auto iter = aParam.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
MOZ_RELEASE_ASSERT(iter.Data());
|
||||
WriteParam(aMsg, iter.Key());
|
||||
WriteParam(aMsg, *(iter.Data()));
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t count;
|
||||
if (!ReadParam(aMsg, aIter, &count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t current = 0; current < count; ++current) {
|
||||
nsAutoString key;
|
||||
if (!ReadParam(aMsg, aIter, &key) || key.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::ModuleRecord> rec(new mozilla::ModuleRecord());
|
||||
if (!ReadParam(aMsg, aIter, rec.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->Put(key, rec.forget());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ModulePaths> {
|
||||
typedef mozilla::ModulePaths paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aParam.mModuleNtPaths.match(
|
||||
[aMsg](const paramType::SetType& aSet) { WriteSet(aMsg, aSet); },
|
||||
[aMsg](const paramType::VecType& aVec) { WriteVector(aMsg, aVec); });
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t len;
|
||||
if (!aMsg->ReadUInt32(aIter, &len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// As noted in the comments for ModulePaths, we only deserialize using the
|
||||
// Vector representation.
|
||||
auto& vec = aResult->mModuleNtPaths.as<paramType::VecType>();
|
||||
if (!vec.reserve(len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < len; ++idx) {
|
||||
nsString str;
|
||||
if (!ReadParam(aMsg, aIter, &str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vec.emplaceBack(std::move(str))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// NB: This function must write out the set in the same format as WriteVector
|
||||
static void WriteSet(Message* aMsg, const paramType::SetType& aSet) {
|
||||
aMsg->WriteUInt32(aSet.Count());
|
||||
for (auto iter = aSet.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
WriteParam(aMsg, iter.Get()->GetKey());
|
||||
}
|
||||
}
|
||||
|
||||
// NB: This function must write out the vector in the same format as WriteSet
|
||||
static void WriteVector(Message* aMsg, const paramType::VecType& aVec) {
|
||||
aMsg->WriteUInt32(aVec.length());
|
||||
for (auto const& item : aVec) {
|
||||
WriteParam(aMsg, item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::UntrustedModulesData> {
|
||||
typedef mozilla::UntrustedModulesData paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt32(aParam.mProcessType);
|
||||
aMsg->WriteULong(aParam.mPid);
|
||||
WriteParam(aMsg, aParam.mElapsed);
|
||||
WriteParam(aMsg, aParam.mModules);
|
||||
|
||||
aMsg->WriteUInt32(aParam.mEvents.length());
|
||||
for (auto& evt : aParam.mEvents) {
|
||||
WriteEvent(aMsg, evt);
|
||||
}
|
||||
|
||||
WriteParam(aMsg, aParam.mStacks);
|
||||
WriteParam(aMsg, aParam.mXULLoadDurationMS);
|
||||
aMsg->WriteUInt32(aParam.mSanitizationFailures);
|
||||
aMsg->WriteUInt32(aParam.mTrustTestFailures);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t processType;
|
||||
if (!aMsg->ReadUInt32(aIter, &processType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->mProcessType = static_cast<GeckoProcessType>(processType);
|
||||
|
||||
if (!aMsg->ReadULong(aIter, &aResult->mPid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mElapsed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mModules)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We read mEvents manually so that we can use ReadEvent defined below.
|
||||
uint32_t eventsLen;
|
||||
if (!ReadParam(aMsg, aIter, &eventsLen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aResult->mEvents.resize(eventsLen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t curEventIdx = 0; curEventIdx < eventsLen; ++curEventIdx) {
|
||||
if (!ReadEvent(aMsg, aIter, &(aResult->mEvents[curEventIdx]),
|
||||
aResult->mModules)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mStacks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mXULLoadDurationMS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aMsg->ReadUInt32(aIter, &aResult->mSanitizationFailures)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aMsg->ReadUInt32(aIter, &aResult->mTrustTestFailures)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Because ProcessedModuleLoadEvent depends on a hash table from
|
||||
// UntrustedModulesData, we do its serialization as part of this
|
||||
// specialization.
|
||||
static void WriteEvent(Message* aMsg,
|
||||
const mozilla::ProcessedModuleLoadEvent& aParam) {
|
||||
aMsg->WriteUInt64(aParam.mProcessUptimeMS);
|
||||
WriteParam(aMsg, aParam.mLoadDurationMS);
|
||||
aMsg->WriteULong(aParam.mThreadId);
|
||||
WriteParam(aMsg, aParam.mThreadName);
|
||||
WriteParam(aMsg, aParam.mRequestedDllName);
|
||||
WriteParam(aMsg, aParam.mBaseAddress);
|
||||
|
||||
// We don't write the ModuleRecord directly; we write its key into the
|
||||
// UntrustedModulesData::mModules hash table.
|
||||
MOZ_ASSERT(aParam.mModule && !aParam.mModule->mResolvedNtName.IsEmpty());
|
||||
WriteParam(aMsg, aParam.mModule->mResolvedNtName);
|
||||
}
|
||||
|
||||
// Because ProcessedModuleLoadEvent depends on a hash table from
|
||||
// UntrustedModulesData, we do its deserialization as part of this
|
||||
// specialization.
|
||||
static bool ReadEvent(const Message* aMsg, PickleIterator* aIter,
|
||||
mozilla::ProcessedModuleLoadEvent* aResult,
|
||||
const mozilla::ModulesMap& aModulesMap) {
|
||||
if (!aMsg->ReadUInt64(aIter, &aResult->mProcessUptimeMS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mLoadDurationMS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aMsg->ReadULong(aIter, &aResult->mThreadId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mThreadName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mRequestedDllName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mBaseAddress)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString resolvedNtName;
|
||||
if (!ReadParam(aMsg, aIter, &resolvedNtName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->mModule = aModulesMap.Get(resolvedNtName);
|
||||
if (!aResult->mModule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ModulesMapResult> {
|
||||
typedef mozilla::ModulesMapResult paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mModules);
|
||||
aMsg->WriteUInt32(aParam.mTrustTestFailures);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mModules)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aMsg->ReadUInt32(aIter, &aResult->mTrustTestFailures)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#else // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// For compiling IPDL on non-Windows platforms
|
||||
using UntrustedModulesData = uint32_t;
|
||||
using ModulePaths = uint32_t;
|
||||
using ModulesMapResult = uint32_t;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#endif // mozilla_UntrustedModulesData_h
|
||||
|
|
|
@ -9,23 +9,18 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/RDDParent.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "ModuleEvaluator.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "private/prpriv.h" // For PR_GetThreadID
|
||||
|
||||
static DWORD ToWin32ThreadId(nsIThread* aThread) {
|
||||
MOZ_ASSERT(aThread);
|
||||
if (!aThread) {
|
||||
return 0UL;
|
||||
}
|
||||
|
@ -37,7 +32,12 @@ static DWORD ToWin32ThreadId(nsIThread* aThread) {
|
|||
return 0UL;
|
||||
}
|
||||
|
||||
return DWORD(::PR_GetThreadID(prThread));
|
||||
PRUint32 tid = ::PR_GetThreadID(prThread);
|
||||
if (!tid) {
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
return DWORD(tid);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -86,22 +86,15 @@ class MOZ_RAII BackgroundPriorityRegion final {
|
|||
const BOOL mIsBackground;
|
||||
};
|
||||
|
||||
/* static */
|
||||
bool UntrustedModulesProcessor::IsSupportedProcessType() {
|
||||
switch (XRE_GetProcessType()) {
|
||||
case GeckoProcessType_Default:
|
||||
case GeckoProcessType_Content:
|
||||
case GeckoProcessType_RDD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
RefPtr<UntrustedModulesProcessor> UntrustedModulesProcessor::Create() {
|
||||
#if defined(EARLY_BETA_OR_EARLIER)
|
||||
if (!IsSupportedProcessType() || !Telemetry::CanRecordReleaseData()) {
|
||||
if (!XRE_IsParentProcess()) {
|
||||
// Not currently supported outside the parent process
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!Telemetry::CanRecordReleaseData()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -130,35 +123,23 @@ void UntrustedModulesProcessor::AddObservers() {
|
|||
nsCOMPtr<nsIObserverService> obsServ(services::GetObserverService());
|
||||
obsServ->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, false);
|
||||
obsServ->AddObserver(this, "xpcom-shutdown-threads", false);
|
||||
if (XRE_IsContentProcess()) {
|
||||
obsServ->AddObserver(this, "content-child-will-shutdown", false);
|
||||
}
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::Disable() {
|
||||
// Ensure that mThread cannot run at low priority anymore
|
||||
BackgroundPriorityRegion::Clear(mThread);
|
||||
|
||||
// No more background processing allowed beyond this point
|
||||
if (!mAllowProcessing.exchange(false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mUnprocessedMutex);
|
||||
CancelScheduledProcessing(lock);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP UntrustedModulesProcessor::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
if (!strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) ||
|
||||
!strcmp(aTopic, "content-child-will-shutdown")) {
|
||||
Disable();
|
||||
if (!strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID)) {
|
||||
// No more background processing allowed beyond this point
|
||||
mAllowProcessing = false;
|
||||
// Ensure that mThread cannot run at low priority anymore
|
||||
BackgroundPriorityRegion::Clear(mThread);
|
||||
|
||||
MutexAutoLock lock(mUnprocessedMutex);
|
||||
CancelScheduledProcessing(lock);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "xpcom-shutdown-threads")) {
|
||||
Disable();
|
||||
mThread->Shutdown();
|
||||
|
||||
RemoveObservers();
|
||||
|
@ -176,13 +157,10 @@ void UntrustedModulesProcessor::RemoveObservers() {
|
|||
nsCOMPtr<nsIObserverService> obsServ(services::GetObserverService());
|
||||
obsServ->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
|
||||
obsServ->RemoveObserver(this, "xpcom-shutdown-threads");
|
||||
if (XRE_IsContentProcess()) {
|
||||
obsServ->RemoveObserver(this, "content-child-will-shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::ScheduleNonEmptyQueueProcessing(
|
||||
const MutexAutoLock& aProofOfLock) {
|
||||
const char* aSource, const MutexAutoLock& aProofOfLock) {
|
||||
// In case something tried to load a DLL during shutdown
|
||||
if (!mThread) {
|
||||
return;
|
||||
|
@ -207,9 +185,9 @@ void UntrustedModulesProcessor::ScheduleNonEmptyQueueProcessing(
|
|||
// Schedule a runnable to trigger background processing once the main thread
|
||||
// has gone idle. We do it this way to ensure that we don't start doing a
|
||||
// bunch of processing during periods of heavy main thread activity.
|
||||
nsCOMPtr<nsIRunnable> idleRunnable(NewCancelableRunnableMethod(
|
||||
nsCOMPtr<nsIRunnable> idleRunnable(NewCancelableRunnableMethod<const char*>(
|
||||
"UntrustedModulesProcessor::DispatchBackgroundProcessing", this,
|
||||
&UntrustedModulesProcessor::DispatchBackgroundProcessing));
|
||||
&UntrustedModulesProcessor::DispatchBackgroundProcessing, aSource));
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThreadQueue(do_AddRef(idleRunnable),
|
||||
EventQueuePriority::Idle))) {
|
||||
|
@ -234,16 +212,17 @@ void UntrustedModulesProcessor::CancelScheduledProcessing(
|
|||
mIdleRunnable = nullptr;
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::DispatchBackgroundProcessing() {
|
||||
void UntrustedModulesProcessor::DispatchBackgroundProcessing(
|
||||
const char* aSource) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable(NewRunnableMethod(
|
||||
nsCOMPtr<nsIRunnable> runnable(NewRunnableMethod<const char*>(
|
||||
"UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue", this,
|
||||
&UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue));
|
||||
&UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue, aSource));
|
||||
|
||||
mThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
@ -264,7 +243,7 @@ void UntrustedModulesProcessor::Enqueue(
|
|||
|
||||
Unused << mUnprocessedModuleLoads.emplaceBack(std::move(aModLoadInfo));
|
||||
|
||||
ScheduleNonEmptyQueueProcessing(lock);
|
||||
ScheduleNonEmptyQueueProcessing(__func__, lock);
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::Enqueue(ModuleLoadInfoVec&& aEvents) {
|
||||
|
@ -281,7 +260,7 @@ void UntrustedModulesProcessor::Enqueue(ModuleLoadInfoVec&& aEvents) {
|
|||
Unused << mUnprocessedModuleLoads.emplaceBack(std::move(event));
|
||||
}
|
||||
|
||||
ScheduleNonEmptyQueueProcessing(lock);
|
||||
ScheduleNonEmptyQueueProcessing(__func__, lock);
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::AssertRunningOnLazyIdleThread() {
|
||||
|
@ -298,79 +277,22 @@ void UntrustedModulesProcessor::AssertRunningOnLazyIdleThread() {
|
|||
RefPtr<UntrustedModulesPromise> UntrustedModulesProcessor::GetProcessedData() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Clear any background priority in case background processing is running.
|
||||
BackgroundPriorityRegion::Clear(mThread);
|
||||
|
||||
RefPtr<UntrustedModulesProcessor> self(this);
|
||||
return InvokeAsync(
|
||||
mThread->SerialEventTarget(), __func__,
|
||||
[self = std::move(self)]() { return self->GetProcessedDataInternal(); });
|
||||
}
|
||||
|
||||
RefPtr<ModulesTrustPromise> UntrustedModulesProcessor::GetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return ModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
RefPtr<UntrustedModulesProcessor> self(this);
|
||||
auto run = [self = std::move(self), modPaths = std::move(aModPaths),
|
||||
runNormal = aRunAtNormalPriority]() mutable {
|
||||
return self->GetModulesTrustInternal(std::move(modPaths), runNormal);
|
||||
};
|
||||
|
||||
if (aRunAtNormalPriority) {
|
||||
// Clear any background priority in case background processing is running.
|
||||
BackgroundPriorityRegion::Clear(mThread);
|
||||
|
||||
return InvokeAsync(mThread->SerialEventTarget(), __func__, std::move(run));
|
||||
}
|
||||
|
||||
RefPtr<ModulesTrustPromise::Private> p(
|
||||
new ModulesTrustPromise::Private(__func__));
|
||||
nsCOMPtr<nsISerialEventTarget> evtTarget(mThread->SerialEventTarget());
|
||||
const char* source = __func__;
|
||||
|
||||
auto runWrap = [evtTarget = std::move(evtTarget), p, source,
|
||||
run = std::move(run)]() mutable -> void {
|
||||
InvokeAsync(evtTarget, source, std::move(run))->ChainTo(p.forget(), source);
|
||||
};
|
||||
|
||||
nsCOMPtr<nsIRunnable> idleRunnable(
|
||||
NS_NewRunnableFunction(source, std::move(runWrap)));
|
||||
|
||||
nsresult rv = NS_DispatchToMainThreadQueue(idleRunnable.forget(),
|
||||
EventQueuePriority::Idle);
|
||||
if (NS_FAILED(rv)) {
|
||||
p->Reject(rv, source);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
RefPtr<UntrustedModulesPromise>
|
||||
UntrustedModulesProcessor::GetProcessedDataInternal() {
|
||||
AssertRunningOnLazyIdleThread();
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return GetProcessedDataInternalChildProcess();
|
||||
}
|
||||
|
||||
ProcessModuleLoadQueue();
|
||||
|
||||
return GetAllProcessedData(__func__);
|
||||
}
|
||||
|
||||
RefPtr<UntrustedModulesPromise> UntrustedModulesProcessor::GetAllProcessedData(
|
||||
const char* aSource) {
|
||||
AssertRunningOnLazyIdleThread();
|
||||
ProcessModuleLoadQueue(__func__);
|
||||
|
||||
UntrustedModulesData result;
|
||||
|
||||
if (!mProcessedModuleLoads) {
|
||||
return UntrustedModulesPromise::CreateAndResolve(Nothing(), aSource);
|
||||
return UntrustedModulesPromise::CreateAndResolve(Nothing(), __func__);
|
||||
}
|
||||
|
||||
result.Swap(mProcessedModuleLoads);
|
||||
|
@ -378,66 +300,11 @@ RefPtr<UntrustedModulesPromise> UntrustedModulesProcessor::GetAllProcessedData(
|
|||
result.mElapsed = TimeStamp::Now() - TimeStamp::ProcessCreation();
|
||||
|
||||
return UntrustedModulesPromise::CreateAndResolve(
|
||||
Some(UntrustedModulesData(std::move(result))), aSource);
|
||||
Some(UntrustedModulesData(std::move(result))), __func__);
|
||||
}
|
||||
|
||||
RefPtr<UntrustedModulesPromise>
|
||||
UntrustedModulesProcessor::GetProcessedDataInternalChildProcess() {
|
||||
AssertRunningOnLazyIdleThread();
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
|
||||
RefPtr<GetModulesTrustPromise> whenProcessed(
|
||||
ProcessModuleLoadQueueChildProcess(Priority::Default));
|
||||
|
||||
RefPtr<UntrustedModulesProcessor> self(this);
|
||||
RefPtr<UntrustedModulesPromise::Private> p(
|
||||
new UntrustedModulesPromise::Private(__func__));
|
||||
nsCOMPtr<nsISerialEventTarget> evtTarget(mThread->SerialEventTarget());
|
||||
|
||||
const char* source = __func__;
|
||||
auto completionRoutine = [evtTarget = std::move(evtTarget), p,
|
||||
self = std::move(self), source,
|
||||
whenProcessed = std::move(whenProcessed)]() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!self->mAllowProcessing) {
|
||||
// We can't do any more work, just reject all the things
|
||||
whenProcessed->Then(
|
||||
GetMainThreadSerialEventTarget(), source,
|
||||
[p, source](Maybe<ModulesMapResultWithLoads>&& aResult) {
|
||||
p->Reject(NS_ERROR_ILLEGAL_DURING_SHUTDOWN, source);
|
||||
},
|
||||
[p, source](nsresult aRv) { p->Reject(aRv, source); });
|
||||
return;
|
||||
}
|
||||
|
||||
whenProcessed->Then(
|
||||
evtTarget, source,
|
||||
[p, self = std::move(self),
|
||||
source](Maybe<ModulesMapResultWithLoads>&& aResult) mutable {
|
||||
if (aResult.isSome()) {
|
||||
self->CompleteProcessing(std::move(aResult.ref()));
|
||||
}
|
||||
self->GetAllProcessedData(source)->ChainTo(p.forget(), source);
|
||||
},
|
||||
[p, source](nsresult aRv) { p->Reject(aRv, source); });
|
||||
};
|
||||
|
||||
// We always send |completionRoutine| on a trip through the main thread
|
||||
// due to some subtlety with |mThread| being a LazyIdleThread: we can only
|
||||
// Dispatch or Then to |mThread| from its creating thread, which is the
|
||||
// main thread. Hopefully we can get rid of this in the future and just
|
||||
// invoke whenProcessed->Then() directly.
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction(__func__, std::move(completionRoutine)));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
p->Reject(rv, __func__);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue() {
|
||||
void UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue(
|
||||
const char* aSource) {
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
@ -448,35 +315,26 @@ void UntrustedModulesProcessor::BackgroundProcessModuleLoadQueue() {
|
|||
return;
|
||||
}
|
||||
|
||||
ProcessModuleLoadQueue();
|
||||
ProcessModuleLoadQueue(aSource);
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> UntrustedModulesProcessor::GetOrAddModuleRecord(
|
||||
ModulesMap& aModules, const ModuleEvaluator& aModEval,
|
||||
const glue::EnhancedModuleLoadInfo& aModLoadInfo) {
|
||||
return GetOrAddModuleRecord(aModules, aModEval,
|
||||
aModLoadInfo.mNtLoadInfo.mSectionName.AsString());
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> UntrustedModulesProcessor::GetOrAddModuleRecord(
|
||||
ModulesMap& aModules, const ModuleEvaluator& aModEval,
|
||||
RefPtr<ModuleRecord> UntrustedModulesProcessor::GetModuleRecord(
|
||||
UntrustedModulesData::ModulesMap& aModules, const ModuleEvaluator& aModEval,
|
||||
const nsAString& aResolvedNtPath) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
nsAutoString resolvedDosPath;
|
||||
if (!NtPathToDosPath(aResolvedNtPath, resolvedDosPath)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto addPtr = aModules.LookupForAdd(aResolvedNtPath);
|
||||
auto addPtr = aModules.LookupForAdd(resolvedDosPath);
|
||||
if (addPtr) {
|
||||
return addPtr.Data();
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> newMod(new ModuleRecord(aResolvedNtPath));
|
||||
if (!(*newMod)) {
|
||||
addPtr.OrRemove();
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<ModuleRecord> newMod(new ModuleRecord(resolvedDosPath));
|
||||
|
||||
Maybe<ModuleTrustFlags> maybeTrust = aModEval.GetTrust(*newMod);
|
||||
if (maybeTrust.isNothing()) {
|
||||
addPtr.OrRemove();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -487,69 +345,10 @@ RefPtr<ModuleRecord> UntrustedModulesProcessor::GetOrAddModuleRecord(
|
|||
return newMod;
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> UntrustedModulesProcessor::GetModuleRecord(
|
||||
const ModulesMap& aModules,
|
||||
const glue::EnhancedModuleLoadInfo& aModuleLoadInfo) {
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
|
||||
return aModules.Get(aModuleLoadInfo.mNtLoadInfo.mSectionName.AsString());
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::BackgroundProcessModuleLoadQueueChildProcess() {
|
||||
RefPtr<GetModulesTrustPromise> whenProcessed(
|
||||
ProcessModuleLoadQueueChildProcess(Priority::Background));
|
||||
|
||||
RefPtr<UntrustedModulesProcessor> self(this);
|
||||
nsCOMPtr<nsISerialEventTarget> evtTarget(mThread->SerialEventTarget());
|
||||
|
||||
const char* source = __func__;
|
||||
auto completionRoutine = [evtTarget = std::move(evtTarget),
|
||||
self = std::move(self), source,
|
||||
whenProcessed = std::move(whenProcessed)]() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!self->mAllowProcessing) {
|
||||
// We can't do any more work, just no-op
|
||||
whenProcessed->Then(
|
||||
GetMainThreadSerialEventTarget(), source,
|
||||
[](Maybe<ModulesMapResultWithLoads>&& aResult) {},
|
||||
[](nsresult aRv) {});
|
||||
return;
|
||||
}
|
||||
|
||||
whenProcessed->Then(
|
||||
evtTarget, source,
|
||||
[self = std::move(self)](Maybe<ModulesMapResultWithLoads>&& aResult) {
|
||||
if (aResult.isNothing() || !self->mAllowProcessing) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
BackgroundPriorityRegion bgRgn;
|
||||
self->CompleteProcessing(std::move(aResult.ref()));
|
||||
},
|
||||
[](nsresult aRv) {});
|
||||
};
|
||||
|
||||
// We always send |completionRoutine| on a trip through the main thread
|
||||
// due to some subtlety with |mThread| being a LazyIdleThread: we can only
|
||||
// Dispatch or Then to |mThread| from its creating thread, which is the
|
||||
// main thread. Hopefully we can get rid of this in the future and just
|
||||
// invoke whenProcessed->Then() directly.
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction(__func__, std::move(completionRoutine)));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
// This function contains multiple |mAllowProcessing| checks so that we can
|
||||
// quickly bail out at the first sign of shutdown. This may be important when
|
||||
// the current thread is running under background priority.
|
||||
void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
|
||||
AssertRunningOnLazyIdleThread();
|
||||
if (!XRE_IsParentProcess()) {
|
||||
BackgroundProcessModuleLoadQueueChildProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::ProcessModuleLoadQueue(const char* aSource) {
|
||||
Vector<glue::EnhancedModuleLoadInfo> loadsToProcess;
|
||||
|
||||
{ // Scope for lock
|
||||
|
@ -558,7 +357,7 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
|
|||
loadsToProcess.swap(mUnprocessedModuleLoads);
|
||||
}
|
||||
|
||||
if (!mAllowProcessing || loadsToProcess.empty()) {
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -569,7 +368,7 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
|
|||
}
|
||||
|
||||
Telemetry::BatchProcessedStackGenerator stackProcessor;
|
||||
ModulesMap modules;
|
||||
nsRefPtrHashtable<nsStringHashKey, ModuleRecord> modules;
|
||||
|
||||
Maybe<double> maybeXulLoadDuration;
|
||||
Vector<Telemetry::ProcessedStack> processedStacks;
|
||||
|
@ -582,7 +381,8 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> module(GetOrAddModuleRecord(modules, modEval, entry));
|
||||
RefPtr<ModuleRecord> module(GetModuleRecord(
|
||||
modules, modEval, entry.mNtLoadInfo.mSectionName.AsString()));
|
||||
if (!module) {
|
||||
// We failed to obtain trust information about the module.
|
||||
// Don't include test failures in the ping to avoid flooding it.
|
||||
|
@ -654,335 +454,4 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
|
|||
mProcessedModuleLoads.mTrustTestFailures += trustTestFailures;
|
||||
}
|
||||
|
||||
template <typename ActorT>
|
||||
static RefPtr<GetModulesTrustIpcPromise> SendGetModulesTrust(
|
||||
ActorT* aActor, ModulePaths&& aModPaths, bool aRunAtNormalPriority) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return aActor->SendGetModulesTrust(std::move(aModPaths),
|
||||
aRunAtNormalPriority);
|
||||
}
|
||||
|
||||
RefPtr<GetModulesTrustIpcPromise>
|
||||
UntrustedModulesProcessor::SendGetModulesTrust(ModulePaths&& aModules,
|
||||
Priority aPriority) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
bool runNormal = aPriority == Priority::Default;
|
||||
|
||||
switch (XRE_GetProcessType()) {
|
||||
case GeckoProcessType_Content: {
|
||||
return ::SendGetModulesTrust(dom::ContentChild::GetSingleton(),
|
||||
std::move(aModules), runNormal);
|
||||
}
|
||||
case GeckoProcessType_RDD: {
|
||||
return ::SendGetModulesTrust(RDDParent::GetSingleton(),
|
||||
std::move(aModules), runNormal);
|
||||
}
|
||||
default: {
|
||||
MOZ_ASSERT_UNREACHABLE("Unsupported process type");
|
||||
return GetModulesTrustIpcPromise::CreateAndReject(
|
||||
ipc::ResponseRejectReason::SendError, __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method works very similarly to ProcessModuleLoadQueue, with the
|
||||
* exception that a sandboxed child process does not have sufficient rights to
|
||||
* be able to evaluate a module's trustworthiness. Instead, we accumulate the
|
||||
* resolved paths for all of the modules in this batch and send them to the
|
||||
* parent to determine trustworthiness.
|
||||
*
|
||||
* The parent process returns a list of untrusted modules and invokes
|
||||
* CompleteProcessing to handle the remainder of the process.
|
||||
*
|
||||
* By doing it this way, we minimize the amount of data that needs to be sent
|
||||
* over IPC and avoid the need to process every load's metadata only
|
||||
* to throw most of it away (since most modules will be trusted).
|
||||
*/
|
||||
RefPtr<UntrustedModulesProcessor::GetModulesTrustPromise>
|
||||
UntrustedModulesProcessor::ProcessModuleLoadQueueChildProcess(
|
||||
UntrustedModulesProcessor::Priority aPriority) {
|
||||
AssertRunningOnLazyIdleThread();
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
|
||||
Vector<glue::EnhancedModuleLoadInfo> loadsToProcess;
|
||||
|
||||
{ // Scope for lock
|
||||
MutexAutoLock lock(mUnprocessedMutex);
|
||||
CancelScheduledProcessing(lock);
|
||||
loadsToProcess.swap(mUnprocessedModuleLoads);
|
||||
}
|
||||
|
||||
if (loadsToProcess.empty()) {
|
||||
// Nothing to process
|
||||
return GetModulesTrustPromise::CreateAndResolve(Nothing(), __func__);
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return GetModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
nsTHashtable<nsStringCaseInsensitiveHashKey> moduleNtPathSet;
|
||||
|
||||
// Build a set of modules to be processed by the parent
|
||||
for (glue::EnhancedModuleLoadInfo& entry : loadsToProcess) {
|
||||
if (!mAllowProcessing) {
|
||||
return GetModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
moduleNtPathSet.PutEntry(entry.mNtLoadInfo.mSectionName.AsString());
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return GetModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!moduleNtPathSet.IsEmpty());
|
||||
if (moduleNtPathSet.IsEmpty()) {
|
||||
// Nothing to process
|
||||
return GetModulesTrustPromise::CreateAndResolve(Nothing(), __func__);
|
||||
}
|
||||
|
||||
ModulePaths moduleNtPaths(std::move(moduleNtPathSet));
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return GetModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
RefPtr<UntrustedModulesProcessor> self(this);
|
||||
|
||||
auto invoker = [self = std::move(self),
|
||||
moduleNtPaths = std::move(moduleNtPaths),
|
||||
priority = aPriority]() mutable {
|
||||
return self->SendGetModulesTrust(std::move(moduleNtPaths), priority);
|
||||
};
|
||||
|
||||
RefPtr<GetModulesTrustPromise::Private> p(
|
||||
new GetModulesTrustPromise::Private(__func__));
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return GetModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
// Send the IPC request via the main thread
|
||||
InvokeAsync(GetMainThreadSerialEventTarget(), __func__, std::move(invoker))
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[p, loads = std::move(loadsToProcess)](
|
||||
Maybe<ModulesMapResult>&& aResult) mutable {
|
||||
ModulesMapResultWithLoads result(std::move(aResult),
|
||||
std::move(loads));
|
||||
p->Resolve(Some(ModulesMapResultWithLoads(std::move(result))),
|
||||
__func__);
|
||||
},
|
||||
[p](ipc::ResponseRejectReason aReason) {
|
||||
p->Reject(NS_ERROR_FAILURE, __func__);
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void UntrustedModulesProcessor::CompleteProcessing(
|
||||
UntrustedModulesProcessor::ModulesMapResultWithLoads&& aModulesAndLoads) {
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
AssertRunningOnLazyIdleThread();
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aModulesAndLoads.mModMapResult.isNothing()) {
|
||||
// No untrusted modules in this batch, nothing to save.
|
||||
return;
|
||||
}
|
||||
|
||||
// This map only contains information about modules deemed to be untrusted,
|
||||
// plus xul.dll. Any module referenced by load requests that is *not* in the
|
||||
// map is deemed to be trusted.
|
||||
ModulesMap& modules = aModulesAndLoads.mModMapResult.ref().mModules;
|
||||
const uint32_t& trustTestFailures =
|
||||
aModulesAndLoads.mModMapResult.ref().mTrustTestFailures;
|
||||
LoadsVec& loads = aModulesAndLoads.mLoads;
|
||||
|
||||
if (modules.IsEmpty() && !trustTestFailures) {
|
||||
// No data, nothing to save.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::BatchProcessedStackGenerator stackProcessor;
|
||||
|
||||
Maybe<double> maybeXulLoadDuration;
|
||||
Vector<Telemetry::ProcessedStack> processedStacks;
|
||||
Vector<ProcessedModuleLoadEvent> processedEvents;
|
||||
uint32_t sanitizationFailures = 0;
|
||||
|
||||
if (!modules.IsEmpty()) {
|
||||
for (auto&& item : loads) {
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> module(GetModuleRecord(modules, item));
|
||||
if (!module) {
|
||||
// If module is null then |item| is trusted
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
glue::EnhancedModuleLoadInfo::BacktraceType backtrace =
|
||||
std::move(item.mNtLoadInfo.mBacktrace);
|
||||
ProcessedModuleLoadEvent event(std::move(item), std::move(module));
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
// We don't have a sanitized DLL path, so we cannot include this event
|
||||
// for privacy reasons.
|
||||
++sanitizationFailures;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.IsXULLoad()) {
|
||||
maybeXulLoadDuration = event.mLoadDurationMS;
|
||||
// We saved the XUL load duration, but it is still trusted, so we
|
||||
// continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::ProcessedStack processedStack =
|
||||
stackProcessor.GetStackAndModules(backtrace);
|
||||
|
||||
Unused << processedStacks.emplaceBack(std::move(processedStack));
|
||||
Unused << processedEvents.emplaceBack(std::move(event));
|
||||
}
|
||||
}
|
||||
|
||||
if (processedStacks.empty() && processedEvents.empty() &&
|
||||
!sanitizationFailures && !trustTestFailures) {
|
||||
// Nothing to save
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
mProcessedModuleLoads.AddNewLoads(modules, std::move(processedEvents),
|
||||
std::move(processedStacks));
|
||||
if (maybeXulLoadDuration) {
|
||||
MOZ_ASSERT(!mProcessedModuleLoads.mXULLoadDurationMS);
|
||||
mProcessedModuleLoads.mXULLoadDurationMS = maybeXulLoadDuration;
|
||||
}
|
||||
|
||||
mProcessedModuleLoads.mSanitizationFailures += sanitizationFailures;
|
||||
mProcessedModuleLoads.mTrustTestFailures += trustTestFailures;
|
||||
}
|
||||
|
||||
// The thread priority of this job should match the priority that the child
|
||||
// process is running with, as specified by |aRunAtNormalPriority|.
|
||||
RefPtr<ModulesTrustPromise> UntrustedModulesProcessor::GetModulesTrustInternal(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
AssertRunningOnLazyIdleThread();
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return ModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
if (aRunAtNormalPriority) {
|
||||
return GetModulesTrustInternal(std::move(aModPaths));
|
||||
}
|
||||
|
||||
BackgroundPriorityRegion bgRgn;
|
||||
return GetModulesTrustInternal(std::move(aModPaths));
|
||||
}
|
||||
|
||||
// For each module in |aModPaths|, evaluate its trustworthiness and only send
|
||||
// ModuleRecords for untrusted modules back to the child process. We also save
|
||||
// XUL's ModuleRecord so that the child process may report XUL's load time.
|
||||
RefPtr<ModulesTrustPromise> UntrustedModulesProcessor::GetModulesTrustInternal(
|
||||
ModulePaths&& aModPaths) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
AssertRunningOnLazyIdleThread();
|
||||
|
||||
ModulesMapResult result;
|
||||
|
||||
ModulesMap& modMap = result.mModules;
|
||||
uint32_t& trustTestFailures = result.mTrustTestFailures;
|
||||
|
||||
ModuleEvaluator modEval;
|
||||
MOZ_ASSERT(!!modEval);
|
||||
if (!modEval) {
|
||||
return ModulesTrustPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
|
||||
// This map holds all modules regardless of trust status; we use this to
|
||||
// filter any duplicates from the input.
|
||||
ModulesMap modules;
|
||||
|
||||
for (auto& resolvedNtPath :
|
||||
aModPaths.mModuleNtPaths.as<ModulePaths::VecType>()) {
|
||||
if (!mAllowProcessing) {
|
||||
return ModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!resolvedNtPath.IsEmpty());
|
||||
if (resolvedNtPath.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<ModuleRecord> module(
|
||||
GetOrAddModuleRecord(modules, modEval, resolvedNtPath));
|
||||
if (!module) {
|
||||
// We failed to obtain trust information.
|
||||
++trustTestFailures;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return ModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
if (module->IsTrusted() && !module->IsXUL()) {
|
||||
// If the module is trusted we exclude it from results, unless it's XUL.
|
||||
// (We save XUL so that the child process may report XUL's load time)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAllowProcessing) {
|
||||
return ModulesTrustPromise::CreateAndReject(
|
||||
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
|
||||
}
|
||||
|
||||
modMap.Put(resolvedNtPath, module.forget());
|
||||
}
|
||||
|
||||
return ModulesTrustPromise::CreateAndResolve(std::move(result), __func__);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define mozilla_UntrustedModulesProcessor_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/glue/WindowsDllServices.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
@ -31,11 +30,6 @@ class ModuleEvaluator;
|
|||
using UntrustedModulesPromise =
|
||||
MozPromise<Maybe<UntrustedModulesData>, nsresult, true>;
|
||||
|
||||
using ModulesTrustPromise = MozPromise<ModulesMapResult, nsresult, true>;
|
||||
|
||||
using GetModulesTrustIpcPromise =
|
||||
MozPromise<Maybe<ModulesMapResult>, ipc::ResponseRejectReason, true>;
|
||||
|
||||
class UntrustedModulesProcessor final : public nsIObserver {
|
||||
public:
|
||||
static RefPtr<UntrustedModulesProcessor> Create();
|
||||
|
@ -43,21 +37,11 @@ class UntrustedModulesProcessor final : public nsIObserver {
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Called by DLL Services to explicitly begin shutting down
|
||||
void Disable();
|
||||
|
||||
// Called by DLL Services to submit module load data to the processor
|
||||
void Enqueue(glue::EnhancedModuleLoadInfo&& aModLoadInfo);
|
||||
void Enqueue(ModuleLoadInfoVec&& aEvents);
|
||||
|
||||
// Called by telemetry to retrieve the processed data
|
||||
RefPtr<UntrustedModulesPromise> GetProcessedData();
|
||||
|
||||
// Called by IPC actors in the parent process to evaluate module trust
|
||||
// on behalf of child processes
|
||||
RefPtr<ModulesTrustPromise> GetModulesTrust(ModulePaths&& aModPaths,
|
||||
bool aRunAtNormalPriority);
|
||||
|
||||
UntrustedModulesProcessor(const UntrustedModulesProcessor&) = delete;
|
||||
UntrustedModulesProcessor(UntrustedModulesProcessor&&) = delete;
|
||||
UntrustedModulesProcessor& operator=(const UntrustedModulesProcessor&) =
|
||||
|
@ -67,68 +51,20 @@ class UntrustedModulesProcessor final : public nsIObserver {
|
|||
private:
|
||||
~UntrustedModulesProcessor() = default;
|
||||
UntrustedModulesProcessor();
|
||||
|
||||
static bool IsSupportedProcessType();
|
||||
|
||||
void AddObservers();
|
||||
void RemoveObservers();
|
||||
|
||||
void ScheduleNonEmptyQueueProcessing(const MutexAutoLock& aProofOfLock);
|
||||
void ScheduleNonEmptyQueueProcessing(const char* aSource,
|
||||
const MutexAutoLock& aProofOfLock);
|
||||
void CancelScheduledProcessing(const MutexAutoLock& aProofOfLock);
|
||||
void DispatchBackgroundProcessing();
|
||||
|
||||
void BackgroundProcessModuleLoadQueue();
|
||||
void ProcessModuleLoadQueue();
|
||||
|
||||
using LoadsVec = Vector<glue::EnhancedModuleLoadInfo>;
|
||||
|
||||
class ModulesMapResultWithLoads final {
|
||||
public:
|
||||
ModulesMapResultWithLoads(Maybe<ModulesMapResult>&& aModMapResult,
|
||||
LoadsVec&& aLoads)
|
||||
: mModMapResult(std::move(aModMapResult)), mLoads(std::move(aLoads)) {}
|
||||
Maybe<ModulesMapResult> mModMapResult;
|
||||
LoadsVec mLoads;
|
||||
};
|
||||
|
||||
using GetModulesTrustPromise =
|
||||
MozPromise<Maybe<ModulesMapResultWithLoads>, nsresult, true>;
|
||||
|
||||
enum class Priority { Default, Background };
|
||||
|
||||
RefPtr<GetModulesTrustPromise> ProcessModuleLoadQueueChildProcess(
|
||||
Priority aPriority);
|
||||
void BackgroundProcessModuleLoadQueueChildProcess();
|
||||
|
||||
void DispatchBackgroundProcessing(const char* aSource);
|
||||
void BackgroundProcessModuleLoadQueue(const char* aSource);
|
||||
void ProcessModuleLoadQueue(const char* aSource);
|
||||
void AssertRunningOnLazyIdleThread();
|
||||
|
||||
RefPtr<UntrustedModulesPromise> GetProcessedDataInternal();
|
||||
RefPtr<UntrustedModulesPromise> GetProcessedDataInternalChildProcess();
|
||||
|
||||
RefPtr<ModulesTrustPromise> GetModulesTrustInternal(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority);
|
||||
RefPtr<ModulesTrustPromise> GetModulesTrustInternal(ModulePaths&& aModPaths);
|
||||
|
||||
// These two functions are only called by the parent process
|
||||
RefPtr<ModuleRecord> GetOrAddModuleRecord(
|
||||
ModulesMap& aModules, const ModuleEvaluator& aModEval,
|
||||
const glue::EnhancedModuleLoadInfo& aModLoadInfo);
|
||||
RefPtr<ModuleRecord> GetOrAddModuleRecord(ModulesMap& aModules,
|
||||
const ModuleEvaluator& aModEval,
|
||||
const nsAString& aResolvedNtPath);
|
||||
|
||||
// Only called by child processes
|
||||
RefPtr<ModuleRecord> GetModuleRecord(
|
||||
const ModulesMap& aModules,
|
||||
const glue::EnhancedModuleLoadInfo& aModuleLoadInfo);
|
||||
UntrustedModulesData::ModulesMap& aModules,
|
||||
const ModuleEvaluator& aModEval, const nsAString& aResolvedNtPath);
|
||||
|
||||
RefPtr<GetModulesTrustIpcPromise> SendGetModulesTrust(ModulePaths&& aModules,
|
||||
Priority aPriority);
|
||||
|
||||
void CompleteProcessing(ModulesMapResultWithLoads&& aModulesAndLoads);
|
||||
RefPtr<UntrustedModulesPromise> GetAllProcessedData(const char* aSource);
|
||||
|
||||
private:
|
||||
RefPtr<LazyIdleThread> mThread;
|
||||
|
||||
Mutex mUnprocessedMutex;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -25,7 +24,6 @@ const char* DllServices::kTopicDllLoadedMainThread = "dll-loaded-main-thread";
|
|||
const char* DllServices::kTopicDllLoadedNonMainThread =
|
||||
"dll-loaded-non-main-thread";
|
||||
|
||||
/* static */
|
||||
DllServices* DllServices::Get() {
|
||||
static StaticLocalRefPtr<DllServices> sInstance(
|
||||
[]() -> already_AddRefed<DllServices> {
|
||||
|
@ -52,11 +50,8 @@ DllServices* DllServices::Get() {
|
|||
return sInstance;
|
||||
}
|
||||
|
||||
void DllServices::StartUntrustedModulesProcessor() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mUntrustedModulesProcessor);
|
||||
mUntrustedModulesProcessor = UntrustedModulesProcessor::Create();
|
||||
}
|
||||
DllServices::DllServices()
|
||||
: mUntrustedModulesProcessor(UntrustedModulesProcessor::Create()) {}
|
||||
|
||||
RefPtr<UntrustedModulesPromise> DllServices::GetUntrustedModulesData() {
|
||||
if (!mUntrustedModulesProcessor) {
|
||||
|
@ -67,25 +62,6 @@ RefPtr<UntrustedModulesPromise> DllServices::GetUntrustedModulesData() {
|
|||
return mUntrustedModulesProcessor->GetProcessedData();
|
||||
}
|
||||
|
||||
void DllServices::DisableFull() {
|
||||
if (mUntrustedModulesProcessor) {
|
||||
mUntrustedModulesProcessor->Disable();
|
||||
}
|
||||
|
||||
glue::DllServices::DisableFull();
|
||||
}
|
||||
|
||||
RefPtr<ModulesTrustPromise> DllServices::GetModulesTrust(
|
||||
ModulePaths&& aModPaths, bool aRunAtNormalPriority) {
|
||||
if (!mUntrustedModulesProcessor) {
|
||||
return ModulesTrustPromise::CreateAndReject(NS_ERROR_NOT_IMPLEMENTED,
|
||||
__func__);
|
||||
}
|
||||
|
||||
return mUntrustedModulesProcessor->GetModulesTrust(std::move(aModPaths),
|
||||
aRunAtNormalPriority);
|
||||
}
|
||||
|
||||
void DllServices::NotifyDllLoad(glue::EnhancedModuleLoadInfo&& aModLoadInfo) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -107,10 +83,6 @@ void DllServices::NotifyDllLoad(glue::EnhancedModuleLoadInfo&& aModLoadInfo) {
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsServ(mozilla::services::GetObserverService());
|
||||
if (!obsServ) {
|
||||
return;
|
||||
}
|
||||
|
||||
obsServ->NotifyObservers(nullptr, topic, dllFilePath.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -8,41 +8,22 @@
|
|||
#define mozilla_WinDllServices_h
|
||||
|
||||
#include "mozilla/glue/WindowsDllServices.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UntrustedModulesProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class UntrustedModulesData;
|
||||
class UntrustedModulesProcessor;
|
||||
|
||||
using UntrustedModulesPromise =
|
||||
MozPromise<Maybe<UntrustedModulesData>, nsresult, true>;
|
||||
|
||||
struct ModulePaths;
|
||||
class ModulesMapResult;
|
||||
|
||||
using ModulesTrustPromise = MozPromise<ModulesMapResult, nsresult, true>;
|
||||
|
||||
class DllServices : public glue::DllServices {
|
||||
public:
|
||||
static DllServices* Get();
|
||||
|
||||
virtual void DisableFull() override;
|
||||
|
||||
static const char* kTopicDllLoadedMainThread;
|
||||
static const char* kTopicDllLoadedNonMainThread;
|
||||
|
||||
void StartUntrustedModulesProcessor();
|
||||
|
||||
RefPtr<UntrustedModulesPromise> GetUntrustedModulesData();
|
||||
|
||||
RefPtr<ModulesTrustPromise> GetModulesTrust(ModulePaths&& aModPaths,
|
||||
bool aRunAtNormalPriority);
|
||||
|
||||
private:
|
||||
DllServices() = default;
|
||||
DllServices();
|
||||
~DllServices() = default;
|
||||
|
||||
void NotifyDllLoad(glue::EnhancedModuleLoadInfo&& aModLoadInfo) override;
|
||||
|
|
|
@ -38,7 +38,6 @@ EXPORTS.mozilla += [
|
|||
'Bootstrap.h',
|
||||
'CmdLineAndEnvUtils.h',
|
||||
'SafeMode.h',
|
||||
'UntrustedModulesData.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
|
||||
|
@ -48,6 +47,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
|||
EXPORTS.mozilla += [
|
||||
'ModuleVersionInfo.h',
|
||||
'PolicyChecks.h',
|
||||
'UntrustedModulesData.h',
|
||||
'UntrustedModulesProcessor.h',
|
||||
'WinDllServices.h',
|
||||
'WinTokenUtils.h',
|
||||
|
|
|
@ -4237,7 +4237,6 @@ nsresult XREMain::XRE_mainRun() {
|
|||
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<mozilla::DllServices> dllServices(mozilla::DllServices::Get());
|
||||
dllServices->StartUntrustedModulesProcessor();
|
||||
auto dllServicesDisable =
|
||||
MakeScopeExit([&dllServices]() { dllServices->DisableFull(); });
|
||||
#endif // defined(XP_WIN)
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
# include <process.h>
|
||||
# include <shobjidl.h>
|
||||
# include "mozilla/ipc/WindowsMessageLoop.h"
|
||||
# include "mozilla/WinDllServices.h"
|
||||
#endif
|
||||
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
@ -755,10 +754,6 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
|
|||
// chrome process is killed in cases where the user shuts the system
|
||||
// down or logs off.
|
||||
::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY);
|
||||
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
auto dllSvcDisable =
|
||||
MakeScopeExit([&dllSvc]() { dllSvc->DisableFull(); });
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
||||
|
|
|
@ -190,6 +190,15 @@ class WindowsError final {
|
|||
template <typename T>
|
||||
using WindowsErrorResult = Result<T, WindowsError>;
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
template <typename T>
|
||||
using LauncherResult = WindowsErrorResult<T>;
|
||||
|
||||
using WindowsErrorType = WindowsError;
|
||||
|
||||
#else
|
||||
|
||||
struct LauncherError {
|
||||
LauncherError(const char* aFile, int aLine, WindowsError aWin32Error)
|
||||
: mFile(aFile), mLine(aLine), mError(aWin32Error) {}
|
||||
|
@ -211,32 +220,15 @@ struct LauncherError {
|
|||
bool operator!=(const WindowsError& aOther) const { return mError != aOther; }
|
||||
};
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
template <typename T>
|
||||
using LauncherResult = WindowsErrorResult<T>;
|
||||
|
||||
template <typename T>
|
||||
using LauncherResultWithLineInfo = Result<T, LauncherError>;
|
||||
|
||||
using WindowsErrorType = WindowsError;
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
using LauncherResult = Result<T, LauncherError>;
|
||||
|
||||
template <typename T>
|
||||
using LauncherResultWithLineInfo = LauncherResult<T>;
|
||||
|
||||
using WindowsErrorType = LauncherError;
|
||||
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
using LauncherVoidResult = LauncherResult<Ok>;
|
||||
|
||||
using LauncherVoidResultWithLineInfo = LauncherResultWithLineInfo<Ok>;
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
# define LAUNCHER_ERROR_GENERIC() \
|
||||
|
@ -534,8 +526,6 @@ inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
|
|||
|
||||
class ModuleVersion final {
|
||||
public:
|
||||
constexpr ModuleVersion() : mVersion(0ULL) {}
|
||||
|
||||
explicit ModuleVersion(const VS_FIXEDFILEINFO& aFixedInfo)
|
||||
: mVersion((static_cast<uint64_t>(aFixedInfo.dwFileVersionMS) << 32) |
|
||||
static_cast<uint64_t>(aFixedInfo.dwFileVersionLS)) {}
|
||||
|
@ -565,11 +555,6 @@ class ModuleVersion final {
|
|||
|
||||
bool operator<(const uint64_t& aOther) const { return mVersion < aOther; }
|
||||
|
||||
ModuleVersion& operator=(const uint64_t aIntVersion) {
|
||||
mVersion = aIntVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t mVersion;
|
||||
};
|
||||
|
|
|
@ -2092,8 +2092,7 @@ WinUtils::WhitelistVec WinUtils::BuildWhitelist() {
|
|||
const WinUtils::WhitelistVec& WinUtils::GetWhitelistedPaths() {
|
||||
static WhitelistVec sWhitelist([]() -> WhitelistVec {
|
||||
auto setClearFn = [ptr = &sWhitelist]() -> void {
|
||||
RunOnShutdown([ptr]() -> void { ptr->clear(); },
|
||||
ShutdownPhase::ShutdownFinal);
|
||||
RunOnShutdown([ptr]() -> void { ptr->clear(); }, ShutdownPhase::Shutdown);
|
||||
};
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче