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 |
| 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 shouldn't |
| 460 // be a major performance problem because a new process has a very limited |
| 461 // amount of memory allocated so the majority of the valid range should be |
| 462 // skipped immediately. However if it turns out to be the case it could be |
| 463 // optimized in the specific case of the process being the same as the |
| 464 // current process, which due to ASLR rules the image load address will almost |
| 465 // always match the current process's load address. |
| 466 void* GetProcessBaseAddress(HANDLE process) { |
| 467 MEMORY_BASIC_INFORMATION mem_info = {}; |
| 468 // Start 64KiB above zero page. |
| 469 void* current = reinterpret_cast<void*>(0x10000); |
| 470 base::string16 process_path; |
| 471 |
| 472 if (!GetProcessPath(process, &process_path)) |
| 473 return nullptr; |
| 474 |
| 475 // Walk the virtual memory mappings trying to find image sections. |
| 476 // VirtualQueryEx will return false if it encounters a location outside of |
| 477 // the user memory range. |
| 478 while (::VirtualQueryEx(process, current, &mem_info, sizeof(mem_info))) { |
| 479 base::string16 image_path; |
| 480 if (mem_info.Type == MEM_IMAGE && |
| 481 GetImageFilePath(process, mem_info.BaseAddress, &image_path) && |
| 482 EqualPath(process_path, image_path)) { |
| 483 return mem_info.BaseAddress; |
| 484 } |
| 485 // VirtualQueryEx should fail before overflow, but just in case we'll check |
| 486 // to prevent an infinite loop. |
| 487 base::CheckedNumeric<uintptr_t> next_base = |
| 488 reinterpret_cast<uintptr_t>(mem_info.BaseAddress); |
| 489 next_base += mem_info.RegionSize; |
| 490 if (!next_base.IsValid()) |
| 491 return nullptr; |
| 492 current = reinterpret_cast<void*>(next_base.ValueOrDie()); |
| 493 } |
| 494 |
| 495 return nullptr; |
| 496 } |
| 497 |
413 }; // namespace sandbox | 498 }; // namespace sandbox |
414 | 499 |
415 void ResolveNTFunctionPtr(const char* name, void* ptr) { | 500 void ResolveNTFunctionPtr(const char* name, void* ptr) { |
416 static volatile HMODULE ntdll = NULL; | 501 static volatile HMODULE ntdll = NULL; |
417 | 502 |
418 if (!ntdll) { | 503 if (!ntdll) { |
419 HMODULE ntdll_local = ::GetModuleHandle(sandbox::kNtdllName); | 504 HMODULE ntdll_local = ::GetModuleHandle(sandbox::kNtdllName); |
420 // Use PEImage to sanity-check that we have a valid ntdll handle. | 505 // Use PEImage to sanity-check that we have a valid ntdll handle. |
421 base::win::PEImage ntdll_peimage(ntdll_local); | 506 base::win::PEImage ntdll_peimage(ntdll_local); |
422 CHECK_NT(ntdll_peimage.VerifyMagic()); | 507 CHECK_NT(ntdll_peimage.VerifyMagic()); |
423 // Race-safe way to set static ntdll. | 508 // Race-safe way to set static ntdll. |
424 ::InterlockedCompareExchangePointer( | 509 ::InterlockedCompareExchangePointer( |
425 reinterpret_cast<PVOID volatile*>(&ntdll), ntdll_local, NULL); | 510 reinterpret_cast<PVOID volatile*>(&ntdll), ntdll_local, NULL); |
426 | |
427 } | 511 } |
428 | 512 |
429 CHECK_NT(ntdll); | 513 CHECK_NT(ntdll); |
430 FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr); | 514 FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr); |
431 *function_ptr = ::GetProcAddress(ntdll, name); | 515 *function_ptr = ::GetProcAddress(ntdll, name); |
432 CHECK_NT(*function_ptr); | 516 CHECK_NT(*function_ptr); |
433 } | 517 } |
OLD | NEW |