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 |