| Index: sandbox/win/src/win_utils_unittest.cc
|
| diff --git a/sandbox/win/src/win_utils_unittest.cc b/sandbox/win/src/win_utils_unittest.cc
|
| index 7500798102a8c76fbb2b7e1bcc8a478880abc825..50ded5191531f4f7f3c038505045f05e824a7f51 100644
|
| --- a/sandbox/win/src/win_utils_unittest.cc
|
| +++ b/sandbox/win/src/win_utils_unittest.cc
|
| @@ -3,13 +3,55 @@
|
| // found in the LICENSE file.
|
|
|
| #include <windows.h>
|
| +#include <psapi.h>
|
|
|
| +#include <vector>
|
| +
|
| +#include "base/numerics/safe_conversions.h"
|
| #include "base/win/scoped_handle.h"
|
| +#include "base/win/scoped_process_information.h"
|
| #include "sandbox/win/src/nt_internals.h"
|
| #include "sandbox/win/src/win_utils.h"
|
| #include "sandbox/win/tests/common/test_utils.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| +namespace {
|
| +
|
| +class ScopedTerminateProcess {
|
| + public:
|
| + ScopedTerminateProcess(HANDLE process) : process_(process) {}
|
| +
|
| + ~ScopedTerminateProcess() { ::TerminateProcess(process_, 0); }
|
| +
|
| + private:
|
| + HANDLE process_;
|
| +};
|
| +
|
| +bool GetModuleList(HANDLE process, std::vector<HMODULE>* result) {
|
| + std::vector<HMODULE> modules(256);
|
| + DWORD size_needed = 0;
|
| + if (EnumProcessModules(
|
| + process, &modules[0],
|
| + base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)),
|
| + &size_needed)) {
|
| + result->assign(modules.begin(),
|
| + modules.begin() + (size_needed / sizeof(HMODULE)));
|
| + return true;
|
| + }
|
| + modules.resize(size_needed / sizeof(HMODULE));
|
| + if (EnumProcessModules(
|
| + process, &modules[0],
|
| + base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)),
|
| + &size_needed)) {
|
| + result->assign(modules.begin(),
|
| + modules.begin() + (size_needed / sizeof(HMODULE)));
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| TEST(WinUtils, IsReparsePoint) {
|
| using sandbox::IsReparsePoint;
|
|
|
| @@ -122,3 +164,48 @@ TEST(WinUtils, NtStatusToWin32Error) {
|
| EXPECT_EQ(static_cast<DWORD>(ERROR_ACCESS_DENIED),
|
| GetLastErrorFromNtStatus(STATUS_ACCESS_DENIED));
|
| }
|
| +
|
| +TEST(WinUtils, GetProcessBaseAddress) {
|
| + using sandbox::GetProcessBaseAddress;
|
| + STARTUPINFO start_info = {};
|
| + PROCESS_INFORMATION proc_info = {};
|
| + WCHAR command_line[] = L"notepad";
|
| + start_info.cb = sizeof(start_info);
|
| + start_info.dwFlags = STARTF_USESHOWWINDOW;
|
| + start_info.wShowWindow = SW_HIDE;
|
| + EXPECT_TRUE(::CreateProcessW(nullptr, command_line, nullptr, nullptr, FALSE,
|
| + CREATE_SUSPENDED, nullptr, nullptr, &start_info,
|
| + &proc_info));
|
| + base::win::ScopedProcessInformation scoped_proc_info(proc_info);
|
| + ScopedTerminateProcess process_terminate(scoped_proc_info.process_handle());
|
| + void* base_address = GetProcessBaseAddress(scoped_proc_info.process_handle());
|
| + EXPECT_NE(nullptr, base_address);
|
| + EXPECT_NE(static_cast<DWORD>(-1),
|
| + ::ResumeThread(scoped_proc_info.thread_handle()));
|
| + ::WaitForInputIdle(scoped_proc_info.process_handle(), 1000);
|
| + EXPECT_NE(static_cast<DWORD>(-1),
|
| + ::SuspendThread(scoped_proc_info.thread_handle()));
|
| + // Check again, the process will have done some more memory initialization.
|
| + EXPECT_EQ(base_address,
|
| + GetProcessBaseAddress(scoped_proc_info.process_handle()));
|
| +
|
| + std::vector<HMODULE> modules;
|
| + // Compare against the loader's module list (which should now be initialized).
|
| + // GetModuleList could fail if the target process hasn't fully initialized.
|
| + // If so skip this check and log it as a warning.
|
| + if (GetModuleList(scoped_proc_info.process_handle(), &modules) &&
|
| + modules.size() > 0) {
|
| + // First module should be the main executable.
|
| + EXPECT_EQ(base_address, modules[0]);
|
| + } else {
|
| + LOG(WARNING) << "Couldn't test base address against module list";
|
| + }
|
| + // Fill in some of the virtual memory with 10MiB chunks and try again.
|
| + for (int count = 0; count < 100; ++count) {
|
| + EXPECT_NE(nullptr,
|
| + ::VirtualAllocEx(scoped_proc_info.process_handle(), nullptr,
|
| + 10 * 1024 * 1024, MEM_RESERVE, PAGE_NOACCESS));
|
| + }
|
| + EXPECT_EQ(base_address,
|
| + GetProcessBaseAddress(scoped_proc_info.process_handle()));
|
| +}
|
|
|