Source code

Revision control

Copy as Markdown

Other Tools

# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1549645620 0
# Fri Feb 08 17:07:00 2019 +0000
# Node ID fb5e7c1090a7ddfde22fd2fb5f8a957ccc61fa64
# Parent 5ef34aa8c8918649528048dd60907862a4355e29
Bug 1515088 Part 2: Set LoaderThreads to 1 in the RTL_USER_PROCESS_PARAMETERS structure on child process start-up. r=aklotz
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc
--- a/sandbox/win/src/win_utils.cc
+++ b/sandbox/win/src/win_utils.cc
@@ -170,16 +170,50 @@ void* GetProcessBaseAddress(HANDLE proce
&bytes_read) ||
(sizeof(magic) != bytes_read)) {
return nullptr;
}
if (magic[0] != 'M' || magic[1] != 'Z')
return nullptr;
+#if defined(_M_ARM64)
+ // Windows 10 on ARM64 has multi-threaded DLL loading that does not work with
+ // the sandbox. (On x86 this gets disabled by hook detection code that was not
+ // ported to ARM64). This overwrites the LoaderThreads value in the process
+ // parameters part of the PEB, if it is set to the default of 0 (which
+ // actually means it defaults to 4 loading threads). This is an undocumented
+ // field so there is a, probably small, risk that it might change or move in
+ // the future. In order to slightly guard against that we only update if the
+ // value is currently 0.
+ auto processParameters = reinterpret_cast<uint8_t*>(peb.ProcessParameters);
+ const uint32_t loaderThreadsOffset = 0x40c;
+ uint32_t maxLoaderThreads = 0;
+ BOOL memoryRead = ::ReadProcessMemory(
+ process, processParameters + loaderThreadsOffset, &maxLoaderThreads,
+ sizeof(maxLoaderThreads), &bytes_read);
+ if (memoryRead && (sizeof(maxLoaderThreads) == bytes_read) &&
+ (maxLoaderThreads == 0)) {
+ maxLoaderThreads = 1;
+ auto address = processParameters + loaderThreadsOffset;
+ auto length = sizeof(maxLoaderThreads);
+
+ // First, remove the protection.
+ DWORD old_protection;
+ if (::VirtualProtectEx(process, address, length, PAGE_READWRITE,
+ &old_protection)) {
+ ::WriteProcessMemory(process, address, &maxLoaderThreads, length, NULL);
+
+ // Attempt to restore the original protection.
+ ::VirtualProtectEx(process, address, length, old_protection,
+ &old_protection);
+ }
+ }
+#endif
+
return base_address;
}
absl::optional<ProcessHandleMap> GetCurrentProcessHandles() {
DWORD handle_count;
if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
return absl::nullopt;