Bug 1503538: Part 4 - Add injected static import blocking to launcher process; r=mhowell

Depends on D27145

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Aaron Klotz 2019-04-11 22:32:29 +00:00
Родитель 1a74deabad
Коммит 5b40d0b92a
3 изменённых файлов: 39 добавлений и 26 удалений

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

@ -7,6 +7,7 @@
#include "nsWindowsDllInterceptor.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/ImportDir.h"
#include "mozilla/NativeNt.h"
#include "mozilla/Types.h"
#include "mozilla/WindowsDllBlocklist.h"
@ -304,9 +305,14 @@ static NTSTATUS NTAPI patched_NtMapViewOfSection(
return STATUS_ACCESS_DENIED;
}
#if defined(_MSC_VER)
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif
namespace mozilla {
LauncherVoidResult InitializeDllBlocklistOOP(HANDLE aChildProcess) {
LauncherVoidResult InitializeDllBlocklistOOP(const wchar_t* aFullImagePath,
HANDLE aChildProcess) {
mozilla::CrossProcessDllInterceptor intcpt(aChildProcess);
intcpt.Init(L"ntdll.dll");
bool ok = stub_NtMapViewOfSection.SetDetour(
@ -325,32 +331,36 @@ LauncherVoidResult InitializeDllBlocklistOOP(HANDLE aChildProcess) {
// linked into ntdll, so we obtain the IAT from our own executable and graft
// it onto the child process's IAT, thus enabling the child process's hook to
// safely make its ntdll calls.
mozilla::nt::PEHeaders ourExeImage(::GetModuleHandleW(nullptr));
HMODULE ourModule;
#if defined(_MSC_VER)
ourModule = reinterpret_cast<HMODULE>(&__ImageBase);
#else
ourModule = ::GetModuleHandleW(nullptr);
#endif // defined(_MSC_VER)
mozilla::nt::PEHeaders ourExeImage(ourModule);
if (!ourExeImage) {
return LAUNCHER_ERROR_FROM_WIN32(ERROR_BAD_EXE_FORMAT);
}
PIMAGE_IMPORT_DESCRIPTOR impDesc = ourExeImage.GetIATForModule("ntdll.dll");
if (!impDesc) {
// As part of our mitigation of binary tampering, copy our import directory
// from the original in our executable file.
LauncherVoidResult importDirRestored =
RestoreImportDirectory(aFullImagePath, ourExeImage, aChildProcess,
ourModule);
if (importDirRestored.isErr()) {
return importDirRestored;
}
Maybe<nt::PEHeaders::IATThunks> ntdllThunks =
ourExeImage.GetIATThunksForModule("ntdll.dll");
if (!ntdllThunks) {
return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
}
// This is the pointer we need to write
auto firstIatThunk =
ourExeImage.template RVAToPtr<PIMAGE_THUNK_DATA>(impDesc->FirstThunk);
if (!firstIatThunk) {
return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
}
// Find the length by iterating through the table until we find a null entry
PIMAGE_THUNK_DATA curIatThunk = firstIatThunk;
while (mozilla::nt::PEHeaders::IsValid(curIatThunk)) {
++curIatThunk;
}
ptrdiff_t iatLength =
(curIatThunk - firstIatThunk) * sizeof(IMAGE_THUNK_DATA);
PIMAGE_THUNK_DATA firstIatThunk = ntdllThunks.value().mFirstThunk;
SIZE_T iatLength = ntdllThunks.value().Length();
SIZE_T bytesWritten;
{ // Scope for prot
@ -362,7 +372,7 @@ LauncherVoidResult InitializeDllBlocklistOOP(HANDLE aChildProcess) {
ok = !!::WriteProcessMemory(aChildProcess, firstIatThunk, firstIatThunk,
iatLength, &bytesWritten);
if (!ok) {
if (!ok || bytesWritten != iatLength) {
return LAUNCHER_ERROR_FROM_LAST();
}
}
@ -371,7 +381,7 @@ LauncherVoidResult InitializeDllBlocklistOOP(HANDLE aChildProcess) {
uint32_t newFlags = eDllBlocklistInitFlagWasBootstrapped;
ok = !!::WriteProcessMemory(aChildProcess, &gBlocklistInitFlags, &newFlags,
sizeof(newFlags), &bytesWritten);
if (!ok) {
if (!ok || bytesWritten != sizeof(newFlags)) {
return LAUNCHER_ERROR_FROM_LAST();
}

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

@ -13,7 +13,8 @@
namespace mozilla {
LauncherVoidResult InitializeDllBlocklistOOP(HANDLE aChildProcess);
LauncherVoidResult InitializeDllBlocklistOOP(const wchar_t* aFullImagePath,
HANDLE aChildProcess);
} // namespace mozilla

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

@ -41,7 +41,8 @@
*
* @return Ok if browser startup should proceed
*/
static mozilla::LauncherVoidResult PostCreationSetup(HANDLE aChildProcess,
static mozilla::LauncherVoidResult PostCreationSetup(const wchar_t* aFullImagePath,
HANDLE aChildProcess,
HANDLE aChildMainThread,
const bool aIsSafeMode) {
// The launcher process's DLL blocking code is incompatible with ASAN because
@ -50,7 +51,7 @@ static mozilla::LauncherVoidResult PostCreationSetup(HANDLE aChildProcess,
#if defined(MOZ_ASAN) || defined(_M_ARM64)
return mozilla::Ok();
#else
return mozilla::InitializeDllBlocklistOOP(aChildProcess);
return mozilla::InitializeDllBlocklistOOP(aFullImagePath, aChildProcess);
#endif // defined(MOZ_ASAN) || defined(_M_ARM64)
}
@ -332,7 +333,8 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
nsAutoHandle mainThread(pi.hThread);
LauncherVoidResult setupResult =
PostCreationSetup(process.get(), mainThread.get(), isSafeMode.value());
PostCreationSetup(argv[0], process.get(), mainThread.get(),
isSafeMode.value());
if (setupResult.isErr()) {
HandleLauncherError(setupResult);
::TerminateProcess(process.get(), 1);