38_arm64_set_LoaderThreads.patch (2564B)
1 # HG changeset patch 2 # User Bob Owen <bobowencode@gmail.com> 3 # Date 1549645620 0 4 # Fri Feb 08 17:07:00 2019 +0000 5 # Node ID fb5e7c1090a7ddfde22fd2fb5f8a957ccc61fa64 6 # Parent 5ef34aa8c8918649528048dd60907862a4355e29 7 Bug 1515088 Part 2: Set LoaderThreads to 1 in the RTL_USER_PROCESS_PARAMETERS structure on child process start-up. r=aklotz 8 9 diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc 10 --- a/sandbox/win/src/win_utils.cc 11 +++ b/sandbox/win/src/win_utils.cc 12 @@ -170,16 +170,50 @@ void* GetProcessBaseAddress(HANDLE proce 13 &bytes_read) || 14 (sizeof(magic) != bytes_read)) { 15 return nullptr; 16 } 17 18 if (magic[0] != 'M' || magic[1] != 'Z') 19 return nullptr; 20 21 +#if defined(_M_ARM64) 22 + // Windows 10 on ARM64 has multi-threaded DLL loading that does not work with 23 + // the sandbox. (On x86 this gets disabled by hook detection code that was not 24 + // ported to ARM64). This overwrites the LoaderThreads value in the process 25 + // parameters part of the PEB, if it is set to the default of 0 (which 26 + // actually means it defaults to 4 loading threads). This is an undocumented 27 + // field so there is a, probably small, risk that it might change or move in 28 + // the future. In order to slightly guard against that we only update if the 29 + // value is currently 0. 30 + auto processParameters = reinterpret_cast<uint8_t*>(peb.ProcessParameters); 31 + const uint32_t loaderThreadsOffset = 0x40c; 32 + uint32_t maxLoaderThreads = 0; 33 + BOOL memoryRead = ::ReadProcessMemory( 34 + process, processParameters + loaderThreadsOffset, &maxLoaderThreads, 35 + sizeof(maxLoaderThreads), &bytes_read); 36 + if (memoryRead && (sizeof(maxLoaderThreads) == bytes_read) && 37 + (maxLoaderThreads == 0)) { 38 + maxLoaderThreads = 1; 39 + auto address = processParameters + loaderThreadsOffset; 40 + auto length = sizeof(maxLoaderThreads); 41 + 42 + // First, remove the protection. 43 + DWORD old_protection; 44 + if (::VirtualProtectEx(process, address, length, PAGE_READWRITE, 45 + &old_protection)) { 46 + ::WriteProcessMemory(process, address, &maxLoaderThreads, length, NULL); 47 + 48 + // Attempt to restore the original protection. 49 + ::VirtualProtectEx(process, address, length, old_protection, 50 + &old_protection); 51 + } 52 + } 53 +#endif 54 + 55 return base_address; 56 } 57 58 absl::optional<ProcessHandleMap> GetCurrentProcessHandles() { 59 DWORD handle_count; 60 if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) 61 return absl::nullopt;