Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/win/src/win_utils.h" | 5 #include "sandbox/win/src/win_utils.h" |
| 6 | 6 |
| 7 #include <psapi.h> | |
| 7 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | |
| 8 | 10 |
| 9 #include <map> | 11 #include <map> |
| 10 #include <memory> | 12 #include <memory> |
| 13 #include <vector> | |
| 11 | 14 |
| 12 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/numerics/safe_math.h" | |
| 17 #include "base/strings/string16.h" | |
| 13 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 14 #include "base/win/pe_image.h" | 19 #include "base/win/pe_image.h" |
| 15 #include "sandbox/win/src/internal_types.h" | 20 #include "sandbox/win/src/internal_types.h" |
| 16 #include "sandbox/win/src/nt_internals.h" | 21 #include "sandbox/win/src/nt_internals.h" |
| 17 #include "sandbox/win/src/sandbox_nt_util.h" | 22 #include "sandbox/win/src/sandbox_nt_util.h" |
| 18 | 23 |
| 19 namespace { | 24 namespace { |
| 20 | 25 |
| 21 // Holds the information about a known registry key. | 26 // Holds the information about a known registry key. |
| 22 struct KnownReservedKey { | 27 struct KnownReservedKey { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 | 102 |
| 98 const wchar_t kNTDotPrefix[] = L"\\\\.\\"; | 103 const wchar_t kNTDotPrefix[] = L"\\\\.\\"; |
| 99 const size_t kNTDotPrefixLen = arraysize(kNTDotPrefix) - 1; | 104 const size_t kNTDotPrefixLen = arraysize(kNTDotPrefix) - 1; |
| 100 | 105 |
| 101 // Removes "\\\\.\\" from the path. | 106 // Removes "\\\\.\\" from the path. |
| 102 void RemoveImpliedDevice(base::string16* path) { | 107 void RemoveImpliedDevice(base::string16* path) { |
| 103 if (0 == path->compare(0, kNTDotPrefixLen, kNTDotPrefix)) | 108 if (0 == path->compare(0, kNTDotPrefixLen, kNTDotPrefix)) |
| 104 *path = path->substr(kNTDotPrefixLen); | 109 *path = path->substr(kNTDotPrefixLen); |
| 105 } | 110 } |
| 106 | 111 |
| 112 // Get the native path to the process. | |
| 113 bool GetProcessPath(HANDLE process, base::string16* path) { | |
| 114 wchar_t process_name[MAX_PATH]; | |
| 115 DWORD size = MAX_PATH; | |
| 116 if (::QueryFullProcessImageNameW(process, PROCESS_NAME_NATIVE, process_name, | |
| 117 &size)) { | |
| 118 *path = process_name; | |
| 119 return true; | |
| 120 } | |
| 121 // Process name is potentially greater than MAX_PATH, try larger max size. | |
| 122 std::vector<wchar_t> process_name_buffer(SHRT_MAX); | |
| 123 size = SHRT_MAX; | |
| 124 if (::QueryFullProcessImageNameW(process, PROCESS_NAME_NATIVE, | |
| 125 &process_name_buffer[0], &size)) { | |
| 126 *path = &process_name_buffer[0]; | |
| 127 return true; | |
| 128 } | |
| 129 return false; | |
| 130 } | |
| 131 | |
| 132 // Get the native path for a mapped file. | |
| 133 bool GetImageFilePath(HANDLE process, | |
| 134 void* base_address, | |
| 135 base::string16* path) { | |
| 136 wchar_t mapped_path[MAX_PATH]; | |
| 137 if (::GetMappedFileNameW(process, base_address, mapped_path, MAX_PATH)) { | |
| 138 *path = mapped_path; | |
| 139 return true; | |
| 140 } | |
| 141 // Image name is potentially greater than MAX_PATH, try larger max size. | |
| 142 std::vector<wchar_t> mapped_path_buffer(SHRT_MAX); | |
| 143 if (::GetMappedFileNameW(process, base_address, &mapped_path_buffer[0], | |
| 144 SHRT_MAX)) { | |
| 145 *path = &mapped_path_buffer[0]; | |
| 146 return true; | |
| 147 } | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 107 } // namespace | 151 } // namespace |
| 108 | 152 |
| 109 namespace sandbox { | 153 namespace sandbox { |
| 110 | 154 |
| 111 // Returns true if the provided path points to a pipe. | 155 // Returns true if the provided path points to a pipe. |
| 112 bool IsPipe(const base::string16& path) { | 156 bool IsPipe(const base::string16& path) { |
| 113 size_t start = 0; | 157 size_t start = 0; |
| 114 if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) | 158 if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) |
| 115 start = sandbox::kNTPrefixLen; | 159 start = sandbox::kNTPrefixLen; |
| 116 | 160 |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 | 447 |
| 404 return ok; | 448 return ok; |
| 405 } | 449 } |
| 406 | 450 |
| 407 DWORD GetLastErrorFromNtStatus(NTSTATUS status) { | 451 DWORD GetLastErrorFromNtStatus(NTSTATUS status) { |
| 408 RtlNtStatusToDosErrorFunction NtStatusToDosError = nullptr; | 452 RtlNtStatusToDosErrorFunction NtStatusToDosError = nullptr; |
| 409 ResolveNTFunctionPtr("RtlNtStatusToDosError", &NtStatusToDosError); | 453 ResolveNTFunctionPtr("RtlNtStatusToDosError", &NtStatusToDosError); |
| 410 return NtStatusToDosError(status); | 454 return NtStatusToDosError(status); |
| 411 } | 455 } |
| 412 | 456 |
| 457 // This function walks the virtual memory map using VirtualQueryEx to find | |
|
Will Harris
2016/09/08 16:54:03
I think some of this comment should be in the .h e
| |
| 458 // the main executable's image section. We attempt to find the first image | |
| 459 // section which matches the path returned for the process. This should only | |
| 460 // be used on suspended processes, and ideally only ones which have not been | |
|
Will Harris
2016/09/08 16:54:03
can you do some sort of check that the process is
| |
| 461 // started. There's a slim chance that a process could map its own executables | |
| 462 // file multiple times, but this is pretty unlikely as it's not necessary. | |
| 463 // This shouldn't be a major performance problem because a new process has a | |
| 464 // very limited amount of memory allocated so the majority of the valid range | |
| 465 // should be skipped immediately. However if it turns out to be the case it | |
| 466 // could be optimized in the specific case of the process being the same as the | |
| 467 // current process, which due to ASLR rules the image load address will almost | |
| 468 // always match the current process's load address. | |
| 469 void* GetProcessBaseAddress(HANDLE process) { | |
| 470 MEMORY_BASIC_INFORMATION mem_info = {}; | |
| 471 // Start 64KiB above zero page. | |
| 472 void* current = reinterpret_cast<void*>(0x10000); | |
| 473 base::string16 process_path; | |
| 474 | |
| 475 if (!GetProcessPath(process, &process_path)) | |
| 476 return nullptr; | |
| 477 | |
| 478 // Walk the virtual memory mappings trying to find image sections. | |
| 479 // VirtualQueryEx will return false if it encounters a location outside of | |
| 480 // the user memory range. | |
| 481 while (::VirtualQueryEx(process, current, &mem_info, sizeof(mem_info))) { | |
| 482 base::string16 image_path; | |
| 483 if (mem_info.Type == MEM_IMAGE && | |
| 484 GetImageFilePath(process, mem_info.BaseAddress, &image_path) && | |
| 485 EqualPath(process_path, image_path)) { | |
| 486 return mem_info.BaseAddress; | |
| 487 } | |
| 488 // VirtualQueryEx should fail before overflow, but just in case we'll check | |
| 489 // to prevent an infinite loop. | |
| 490 base::CheckedNumeric<uintptr_t> next_base = | |
| 491 reinterpret_cast<uintptr_t>(mem_info.BaseAddress); | |
| 492 next_base += mem_info.RegionSize; | |
| 493 if (!next_base.IsValid()) | |
| 494 return nullptr; | |
| 495 current = reinterpret_cast<void*>(next_base.ValueOrDie()); | |
| 496 } | |
| 497 | |
| 498 return nullptr; | |
| 499 } | |
| 500 | |
| 413 }; // namespace sandbox | 501 }; // namespace sandbox |
| 414 | 502 |
| 415 void ResolveNTFunctionPtr(const char* name, void* ptr) { | 503 void ResolveNTFunctionPtr(const char* name, void* ptr) { |
| 416 static volatile HMODULE ntdll = NULL; | 504 static volatile HMODULE ntdll = NULL; |
| 417 | 505 |
| 418 if (!ntdll) { | 506 if (!ntdll) { |
| 419 HMODULE ntdll_local = ::GetModuleHandle(sandbox::kNtdllName); | 507 HMODULE ntdll_local = ::GetModuleHandle(sandbox::kNtdllName); |
| 420 // Use PEImage to sanity-check that we have a valid ntdll handle. | 508 // Use PEImage to sanity-check that we have a valid ntdll handle. |
| 421 base::win::PEImage ntdll_peimage(ntdll_local); | 509 base::win::PEImage ntdll_peimage(ntdll_local); |
| 422 CHECK_NT(ntdll_peimage.VerifyMagic()); | 510 CHECK_NT(ntdll_peimage.VerifyMagic()); |
| 423 // Race-safe way to set static ntdll. | 511 // Race-safe way to set static ntdll. |
| 424 ::InterlockedCompareExchangePointer( | 512 ::InterlockedCompareExchangePointer( |
| 425 reinterpret_cast<PVOID volatile*>(&ntdll), ntdll_local, NULL); | 513 reinterpret_cast<PVOID volatile*>(&ntdll), ntdll_local, NULL); |
| 426 | |
| 427 } | 514 } |
| 428 | 515 |
| 429 CHECK_NT(ntdll); | 516 CHECK_NT(ntdll); |
| 430 FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr); | 517 FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr); |
| 431 *function_ptr = ::GetProcAddress(ntdll, name); | 518 *function_ptr = ::GetProcAddress(ntdll, name); |
| 432 CHECK_NT(*function_ptr); | 519 CHECK_NT(*function_ptr); |
| 433 } | 520 } |
| OLD | NEW |