Bug 1322554: Interpose kernel32!BaseThreadInitThunk to add verification of thread start addresses; r=aklotz,dmajor

MozReview-Commit-ID: 8Jm1PXyRrEr

--HG--
extra : rebase_source : 1145dfccaca72b58145f0100a4e313d1c9d685be
This commit is contained in:
Carl Corcoran 2017-05-24 11:56:40 +02:00
parent 99947c9c38
commit d984e671a7
2 changed files with 61 additions and 0 deletions

View File

@ -297,6 +297,12 @@ printf_stderr(const char *fmt, ...)
fclose(fp);
}
#ifdef _M_IX86
typedef void (__fastcall* BaseThreadInitThunk_func)(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
static BaseThreadInitThunk_func stub_BaseThreadInitThunk = nullptr;
#endif
typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
static LdrLoadDll_func stub_LdrLoadDll;
@ -766,6 +772,46 @@ continue_loading:
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
}
#ifdef _M_IX86
static bool
ShouldBlockThread(void* aStartAddress)
{
// Allows crashfirefox.exe to continue to work. Also if your threadproc is null, this crash is intentional.
if (aStartAddress == 0)
return false;
bool shouldBlock = false;
MEMORY_BASIC_INFORMATION startAddressInfo = {0};
if (VirtualQuery(aStartAddress, &startAddressInfo, sizeof(startAddressInfo))) {
shouldBlock |= startAddressInfo.State != MEM_COMMIT;
shouldBlock |= startAddressInfo.Protect != PAGE_EXECUTE_READ;
}
return shouldBlock;
}
// Allows blocked threads to still run normally through BaseThreadInitThunk, in case there's any magic there that we shouldn't skip.
static DWORD WINAPI
NopThreadProc(void* /* aThreadParam */)
{
return 0;
}
static MOZ_NORETURN void __fastcall
patched_BaseThreadInitThunk(BOOL aIsInitialThread, void* aStartAddress,
void* aThreadParam)
{
if (ShouldBlockThread(aStartAddress)) {
aStartAddress = NopThreadProc;
}
stub_BaseThreadInitThunk(aIsInitialThread, aStartAddress, aThreadParam);
}
#endif // _M_IX86
static WindowsDllInterceptor NtDllIntercept;
static WindowsDllInterceptor Kernel32Intercept;
@ -813,6 +859,18 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
(void**)&stub_RtlInstallFunctionTableCallback);
}
#endif
#ifdef _M_IX86 // Minimize impact; crashes in BaseThreadInitThunk are vastly more frequent on x86
if(!Kernel32Intercept.AddDetour("BaseThreadInitThunk",
reinterpret_cast<intptr_t>(patched_BaseThreadInitThunk),
(void**) &stub_BaseThreadInitThunk)) {
#ifdef DEBUG
printf_stderr("BaseThreadInitThunk hook failed\n");
#endif
}
#endif // _M_IX86
}
MFBT_API void

View File

@ -519,6 +519,9 @@ int main()
#endif
TestHook(TestTlsAlloc, "kernel32.dll", "TlsAlloc") &&
TestHook(TestTlsFree, "kernel32.dll", "TlsFree") &&
#ifdef _M_IX86
TestDetour("kernel32.dll", "BaseThreadInitThunk") &&
#endif
TestDetour("ntdll.dll", "LdrLoadDll")) {
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
return 0;