Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: sandbox/src/Wow64.cc

Issue 6610029: Create a "GetWOW64Status()" utility function and make the rest of the codebas... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 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/src/wow64.h" 5 #include "sandbox/src/wow64.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/scoped_ptr.h" 10 #include "base/scoped_ptr.h"
11 #include "sandbox/src/sandbox.h" 11 #include "base/win/windows_version.h"
12 #include "sandbox/src/target_process.h" 12 #include "sandbox/src/target_process.h"
13 13
14 namespace { 14 namespace {
15 15
16 // Holds the information needed for the interception of NtMapViewOfSection on 16 // Holds the information needed for the interception of NtMapViewOfSection on
17 // 64 bits. 17 // 64 bits.
18 // Warning: do not modify this definition without changing also the code on the 18 // Warning: do not modify this definition without changing also the code on the
19 // 64 bit helper process. 19 // 64 bit helper process.
20 struct PatchInfo32 { 20 struct PatchInfo32 {
21 HANDLE dll_load; // Event to signal the broker. 21 HANDLE dll_load; // Event to signal the broker.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 namespace sandbox { 73 namespace sandbox {
74 74
75 Wow64::~Wow64() { 75 Wow64::~Wow64() {
76 if (dll_load_) 76 if (dll_load_)
77 ::CloseHandle(dll_load_); 77 ::CloseHandle(dll_load_);
78 78
79 if (continue_load_) 79 if (continue_load_)
80 ::CloseHandle(continue_load_); 80 ::CloseHandle(continue_load_);
81 } 81 }
82 82
83 bool Wow64::IsWow64() {
84 if (init_)
85 return is_wow64_;
86
87 is_wow64_ = false;
88
89 HMODULE kernel32 = ::GetModuleHandle(sandbox::kKerneldllName);
90 if (!kernel32)
91 return false;
92
93 IsWow64ProcessFunction is_wow64_process = reinterpret_cast<
94 IsWow64ProcessFunction>(::GetProcAddress(kernel32, "IsWow64Process"));
95
96 init_ = true;
97 if (!is_wow64_process)
98 return false;
99
100 BOOL wow64;
101 if (!is_wow64_process(::GetCurrentProcess(), &wow64))
102 return false;
103
104 if (wow64)
105 is_wow64_ = true;
106
107 return is_wow64_;
108 }
109
110 // The basic idea is to allocate one page of memory on the child, and initialize 83 // The basic idea is to allocate one page of memory on the child, and initialize
111 // the first part of it with our version of PatchInfo32. Then launch the helper 84 // the first part of it with our version of PatchInfo32. Then launch the helper
112 // process passing it that address on the child. The helper process will patch 85 // process passing it that address on the child. The helper process will patch
113 // the 64 bit version of NtMapViewOfFile, and the interception will signal the 86 // the 64 bit version of NtMapViewOfFile, and the interception will signal the
114 // first event on the buffer. We'll be waiting on that event and after the 32 87 // first event on the buffer. We'll be waiting on that event and after the 32
115 // bit version of ntdll is loaded, we'll remove the interception and return to 88 // bit version of ntdll is loaded, we'll remove the interception and return to
116 // our caller. 89 // our caller.
117 bool Wow64::WaitForNtdll(DWORD timeout_ms) { 90 bool Wow64::WaitForNtdll() {
118 DCHECK(!init_); 91 if (base::win::GetWOW64Status() != base::win::WOW64_ENABLED)
119 if (!IsWow64())
120 return true; 92 return true;
121 93
122 const size_t page_size = 4096; 94 const size_t page_size = 4096;
123 95
124 // Create some default manual reset un-named events, not signaled. 96 // Create some default manual reset un-named events, not signaled.
125 dll_load_ = ::CreateEvent(NULL, TRUE, FALSE, NULL); 97 dll_load_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
126 continue_load_ = ::CreateEvent(NULL, TRUE, FALSE, NULL); 98 continue_load_ = ::CreateEvent(NULL, TRUE, FALSE, NULL);
127 HANDLE current_process = ::GetCurrentProcess(); 99 HANDLE current_process = ::GetCurrentProcess();
128 HANDLE remote_load, remote_continue; 100 HANDLE remote_load, remote_continue;
129 DWORD access = EVENT_MODIFY_STATE | SYNCHRONIZE; 101 DWORD access = EVENT_MODIFY_STATE | SYNCHRONIZE;
(...skipping 14 matching lines...) Expand all
144 PatchInfo32 local_patch_info = {0}; 116 PatchInfo32 local_patch_info = {0};
145 local_patch_info.dll_load = remote_load; 117 local_patch_info.dll_load = remote_load;
146 local_patch_info.continue_load = remote_continue; 118 local_patch_info.continue_load = remote_continue;
147 SIZE_T written; 119 SIZE_T written;
148 if (!::WriteProcessMemory(child_->Process(), patch_info, &local_patch_info, 120 if (!::WriteProcessMemory(child_->Process(), patch_info, &local_patch_info,
149 offsetof(PatchInfo32, section), &written)) 121 offsetof(PatchInfo32, section), &written))
150 return false; 122 return false;
151 if (offsetof(PatchInfo32, section) != written) 123 if (offsetof(PatchInfo32, section) != written)
152 return false; 124 return false;
153 125
154 if (!RunWowHelper(buffer, timeout_ms)) 126 if (!RunWowHelper(buffer))
155 return false; 127 return false;
156 128
157 // The child is intercepted on 64 bit, go on and wait for our event. 129 // The child is intercepted on 64 bit, go on and wait for our event.
158 if (!DllMapped(timeout_ms)) 130 if (!DllMapped())
159 return false; 131 return false;
160 132
161 // The 32 bit version is available, cleanup the child. 133 // The 32 bit version is available, cleanup the child.
162 return Restore64Code(child_->Process(), patch_info); 134 return Restore64Code(child_->Process(), patch_info);
163 } 135 }
164 136
165 bool Wow64::RunWowHelper(void* buffer, DWORD timeout_ms) { 137 bool Wow64::RunWowHelper(void* buffer) {
166 COMPILE_ASSERT(sizeof(buffer) <= sizeof(timeout_ms), unsupported_64_bits); 138 COMPILE_ASSERT(sizeof(buffer) <= sizeof DWORD, unsupported_64_bits);
167 139
168 // Get the path to the helper (beside the exe). 140 // Get the path to the helper (beside the exe).
169 wchar_t prog_name[MAX_PATH]; 141 wchar_t prog_name[MAX_PATH];
170 GetModuleFileNameW(NULL, prog_name, MAX_PATH); 142 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
171 std::wstring path(prog_name); 143 std::wstring path(prog_name);
172 size_t name_pos = path.find_last_of(L"\\"); 144 size_t name_pos = path.find_last_of(L"\\");
173 if (std::wstring::npos == name_pos) 145 if (std::wstring::npos == name_pos)
174 return false; 146 return false;
175 path.resize(name_pos + 1); 147 path.resize(name_pos + 1);
176 148
177 std::wstringstream command; 149 std::wstringstream command;
178 command << std::hex << std::showbase << L"\"" << path << 150 command << std::hex << std::showbase << L"\"" << path <<
179 L"wow_helper.exe\" " << child_->ProcessId() << " " << 151 L"wow_helper.exe\" " << child_->ProcessId() << " " <<
180 bit_cast<ULONG>(buffer); 152 bit_cast<ULONG>(buffer);
181 153
182 scoped_ptr_malloc<wchar_t> writable_command(_wcsdup(command.str().c_str())); 154 scoped_ptr_malloc<wchar_t> writable_command(_wcsdup(command.str().c_str()));
183 155
184 STARTUPINFO startup_info = {0}; 156 STARTUPINFO startup_info = {0};
185 startup_info.cb = sizeof(startup_info); 157 startup_info.cb = sizeof(startup_info);
186 PROCESS_INFORMATION process_info; 158 PROCESS_INFORMATION process_info;
187 if (!::CreateProcess(NULL, writable_command.get(), NULL, NULL, FALSE, 0, NULL, 159 if (!::CreateProcess(NULL, writable_command.get(), NULL, NULL, FALSE, 0, NULL,
188 NULL, &startup_info, &process_info)) 160 NULL, &startup_info, &process_info))
189 return false; 161 return false;
190 162
191 DWORD reason = ::WaitForSingleObject(process_info.hProcess, timeout_ms); 163 DWORD reason = ::WaitForSingleObject(process_info.hProcess, INFINITE);
192 164
193 DWORD code; 165 DWORD code;
194 bool ok = ::GetExitCodeProcess(process_info.hProcess, &code) ? true : false; 166 bool ok = ::GetExitCodeProcess(process_info.hProcess, &code) ? true : false;
195 167
196 ::CloseHandle(process_info.hProcess); 168 ::CloseHandle(process_info.hProcess);
197 ::CloseHandle(process_info.hThread); 169 ::CloseHandle(process_info.hThread);
198 170
199 if (WAIT_TIMEOUT == reason) 171 if (WAIT_TIMEOUT == reason)
200 return false; 172 return false;
201 173
202 return ok && (0 == code); 174 return ok && (0 == code);
203 } 175 }
204 176
205 // First we must wake up the child, then wait for dll loads on the child until 177 // First we must wake up the child, then wait for dll loads on the child until
206 // the one we care is loaded; at that point we must suspend the child again. 178 // the one we care is loaded; at that point we must suspend the child again.
207 bool Wow64::DllMapped(DWORD timeout_ms) { 179 bool Wow64::DllMapped() {
208 if (1 != ::ResumeThread(child_->MainThread())) { 180 if (1 != ::ResumeThread(child_->MainThread())) {
209 NOTREACHED(); 181 NOTREACHED();
210 return false; 182 return false;
211 } 183 }
212 184
213 for (;;) { 185 for (;;) {
214 DWORD reason = ::WaitForSingleObject(dll_load_, timeout_ms); 186 DWORD reason = ::WaitForSingleObject(dll_load_, INFINITE);
215 if (WAIT_TIMEOUT == reason || WAIT_ABANDONED == reason) 187 if (WAIT_TIMEOUT == reason || WAIT_ABANDONED == reason)
216 return false; 188 return false;
217 189
218 if (!::ResetEvent(dll_load_)) 190 if (!::ResetEvent(dll_load_))
219 return false; 191 return false;
220 192
221 bool found = NtdllPresent(); 193 bool found = NtdllPresent();
222 if (found) { 194 if (found) {
223 if (::SuspendThread(child_->MainThread())) 195 if (::SuspendThread(child_->MainThread()))
224 return false; 196 return false;
(...skipping 13 matching lines...) Expand all
238 SIZE_T read; 210 SIZE_T read;
239 if (!::ReadProcessMemory(child_->Process(), ntdll_, &buffer, kBufferSize, 211 if (!::ReadProcessMemory(child_->Process(), ntdll_, &buffer, kBufferSize,
240 &read)) 212 &read))
241 return false; 213 return false;
242 if (kBufferSize != read) 214 if (kBufferSize != read)
243 return false; 215 return false;
244 return true; 216 return true;
245 } 217 }
246 218
247 } // namespace sandbox 219 } // namespace sandbox
OLDNEW
« base/win/windows_version.cc ('K') | « sandbox/src/Wow64.h ('k') | sandbox/src/Wow64_64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698