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
@@ -456,20 +456,21 @@ bool GetNtPathFromWin32Path(const std::w
bool rv = GetPathFromHandle(file, nt_path);
::CloseHandle(file);
return rv;
}
bool WriteProtectedChildMemory(HANDLE child_process,
void* address,
const void* buffer,
- size_t length) {
+ size_t length,
+ DWORD writeProtection) {
// First, remove the protections.
DWORD old_protection;
- if (!::VirtualProtectEx(child_process, address, length, PAGE_WRITECOPY,
+ if (!::VirtualProtectEx(child_process, address, length, writeProtection,
&old_protection))
return false;
SIZE_T written;
bool ok =
::WriteProcessMemory(child_process, address, buffer, length, &written) &&
(length == written);
@@ -544,16 +545,40 @@ 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;
+ WriteProtectedChildMemory(process, processParameters + loaderThreadsOffset,
+ &maxLoaderThreads, sizeof(maxLoaderThreads),
+ PAGE_READWRITE);
+ }
+#endif
+
return base_address;
}
DWORD GetTokenInformation(HANDLE token,
TOKEN_INFORMATION_CLASS info_class,
std::unique_ptr<BYTE[]>* buffer) {
// Get the required buffer size.
DWORD size = 0;
diff --git a/sandbox/win/src/win_utils.h b/sandbox/win/src/win_utils.h
--- a/sandbox/win/src/win_utils.h
+++ b/sandbox/win/src/win_utils.h
@@ -111,17 +111,18 @@ HKEY GetReservedKeyFromName(const std::w
bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name);
// Writes |length| bytes from the provided |buffer| into the address space of
// |child_process|, at the specified |address|, preserving the original write
// protection attributes. Returns true on success.
bool WriteProtectedChildMemory(HANDLE child_process,
void* address,
const void* buffer,
- size_t length);
+ size_t length,
+ DWORD writeProtection = PAGE_WRITECOPY);
// Allocates |buffer_bytes| in child (PAGE_READWRITE) and copies data
// from |local_buffer| in this process into |child|. |remote_buffer|
// contains the address in the chile. If a zero byte copy is
// requested |true| is returned and no allocation or copying is
// attempted. Returns false if allocation or copying fails. If
// copying fails, the allocation will be reversed.
bool CopyToChildMemory(HANDLE child,