Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/target_process.h" | 5 #include "sandbox/src/target_process.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/win/pe_image.h" | 9 #include "base/win/pe_image.h" |
| 10 #include "base/win/scoped_process_information.h" | |
| 10 #include "sandbox/src/crosscall_server.h" | 11 #include "sandbox/src/crosscall_server.h" |
| 11 #include "sandbox/src/crosscall_client.h" | 12 #include "sandbox/src/crosscall_client.h" |
| 12 #include "sandbox/src/policy_low_level.h" | 13 #include "sandbox/src/policy_low_level.h" |
| 13 #include "sandbox/src/sandbox_types.h" | 14 #include "sandbox/src/sandbox_types.h" |
| 14 #include "sandbox/src/sharedmem_ipc_server.h" | 15 #include "sandbox/src/sharedmem_ipc_server.h" |
| 15 | 16 |
| 16 namespace { | 17 namespace { |
| 17 | 18 |
| 18 void TerminateTarget(PROCESS_INFORMATION* pi) { | |
| 19 ::CloseHandle(pi->hThread); | |
| 20 ::TerminateProcess(pi->hProcess, 0); | |
| 21 ::CloseHandle(pi->hProcess); | |
| 22 } | |
| 23 | |
| 24 void CopyPolicyToTarget(const void* source, size_t size, void* dest) { | 19 void CopyPolicyToTarget(const void* source, size_t size, void* dest) { |
| 25 if (!source || !size) | 20 if (!source || !size) |
| 26 return; | 21 return; |
| 27 memcpy(dest, source, size); | 22 memcpy(dest, source, size); |
| 28 sandbox::PolicyGlobal* policy = | 23 sandbox::PolicyGlobal* policy = |
| 29 reinterpret_cast<sandbox::PolicyGlobal*>(dest); | 24 reinterpret_cast<sandbox::PolicyGlobal*>(dest); |
| 30 | 25 |
| 31 size_t offset = reinterpret_cast<size_t>(source); | 26 size_t offset = reinterpret_cast<size_t>(source); |
| 32 | 27 |
| 33 for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) { | 28 for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 if (shared_section_) | 129 if (shared_section_) |
| 135 ::CloseHandle(shared_section_); | 130 ::CloseHandle(shared_section_); |
| 136 free(exe_name_); | 131 free(exe_name_); |
| 137 } | 132 } |
| 138 | 133 |
| 139 // Creates the target (child) process suspended and assigns it to the job | 134 // Creates the target (child) process suspended and assigns it to the job |
| 140 // object. | 135 // object. |
| 141 DWORD TargetProcess::Create(const wchar_t* exe_path, | 136 DWORD TargetProcess::Create(const wchar_t* exe_path, |
| 142 const wchar_t* command_line, | 137 const wchar_t* command_line, |
| 143 const wchar_t* desktop, | 138 const wchar_t* desktop, |
| 144 PROCESS_INFORMATION* target_info) { | 139 PROCESS_INFORMATION* target_info) { |
|
alexeypa (please no reviews)
2012/03/29 04:51:35
target_info can also be converted to ScopedProcess
erikwright (departed)
2012/03/30 17:30:27
Extracted to a new CL, see http://codereview.chrom
| |
| 145 exe_name_ = _wcsdup(exe_path); | 140 exe_name_ = _wcsdup(exe_path); |
| 146 | 141 |
| 147 // the command line needs to be writable by CreateProcess(). | 142 // the command line needs to be writable by CreateProcess(). |
| 148 scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line)); | 143 scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line)); |
| 149 scoped_ptr_malloc<wchar_t> desktop_name(desktop ? _wcsdup(desktop) : NULL); | 144 scoped_ptr_malloc<wchar_t> desktop_name(desktop ? _wcsdup(desktop) : NULL); |
| 150 | 145 |
| 151 // Start the target process suspended. | 146 // Start the target process suspended. |
| 152 const DWORD flags = CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB | | 147 const DWORD flags = CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB | |
| 153 CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; | 148 CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; |
| 154 | 149 |
| 155 STARTUPINFO startup_info = {sizeof(STARTUPINFO)}; | 150 STARTUPINFO startup_info = {sizeof(STARTUPINFO)}; |
| 156 if (desktop) { | 151 if (desktop) { |
| 157 startup_info.lpDesktop = desktop_name.get(); | 152 startup_info.lpDesktop = desktop_name.get(); |
| 158 } | 153 } |
| 159 | 154 |
| 160 PROCESS_INFORMATION process_info = {0}; | 155 base::win::ScopedProcessInformation process_info; |
| 161 | 156 |
| 162 if (!::CreateProcessAsUserW(lockdown_token_, | 157 if (!::CreateProcessAsUserW(lockdown_token_, |
| 163 exe_path, | 158 exe_path, |
| 164 cmd_line.get(), | 159 cmd_line.get(), |
| 165 NULL, // No security attribute. | 160 NULL, // No security attribute. |
| 166 NULL, // No thread attribute. | 161 NULL, // No thread attribute. |
| 167 FALSE, // Do not inherit handles. | 162 FALSE, // Do not inherit handles. |
| 168 flags, | 163 flags, |
| 169 NULL, // Use the environment of the caller. | 164 NULL, // Use the environment of the caller. |
| 170 NULL, // Use current directory of the caller. | 165 NULL, // Use current directory of the caller. |
| 171 &startup_info, | 166 &startup_info, |
| 172 &process_info)) { | 167 process_info.Receive())) { |
| 173 return ::GetLastError(); | 168 return ::GetLastError(); |
| 174 } | 169 } |
| 175 | 170 |
| 176 PoisonLowerAddressRange(process_info.hProcess); | 171 PoisonLowerAddressRange(process_info.process_handle()); |
| 177 | 172 |
| 178 DWORD win_result = ERROR_SUCCESS; | 173 DWORD win_result = ERROR_SUCCESS; |
| 179 | 174 |
| 180 // Assign the suspended target to the windows job object | 175 // Assign the suspended target to the windows job object |
| 181 if (!::AssignProcessToJobObject(job_, process_info.hProcess)) { | 176 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { |
| 182 win_result = ::GetLastError(); | 177 win_result = ::GetLastError(); |
| 183 // It might be a security breach if we let the target run outside the job | 178 // It might be a security breach if we let the target run outside the job |
| 184 // so kill it before it causes damage | 179 // so kill it before it causes damage |
| 185 TerminateTarget(&process_info); | 180 ::TerminateProcess(process_info.process_handle(), 0); |
| 186 return win_result; | 181 return win_result; |
| 187 } | 182 } |
| 188 | 183 |
| 189 // Change the token of the main thread of the new process for the | 184 // Change the token of the main thread of the new process for the |
| 190 // impersonation token with more rights. This allows the target to start; | 185 // impersonation token with more rights. This allows the target to start; |
| 191 // otherwise it will crash too early for us to help. | 186 // otherwise it will crash too early for us to help. |
| 192 if (!SetThreadToken(&process_info.hThread, initial_token_)) { | 187 { |
| 193 win_result = ::GetLastError(); | 188 HANDLE temp_thread = process_info.thread_handle(); |
| 194 TerminateTarget(&process_info); | 189 if (!SetThreadToken(&temp_thread, initial_token_)) { |
| 195 return win_result; | 190 win_result = ::GetLastError(); |
| 191 ::TerminateProcess(process_info.process_handle(), 0); | |
| 192 return win_result; | |
| 193 } | |
| 196 } | 194 } |
| 197 | 195 |
| 198 CONTEXT context; | 196 CONTEXT context; |
| 199 context.ContextFlags = CONTEXT_ALL; | 197 context.ContextFlags = CONTEXT_ALL; |
| 200 if (!::GetThreadContext(process_info.hThread, &context)) { | 198 if (!::GetThreadContext(process_info.thread_handle(), &context)) { |
| 201 win_result = ::GetLastError(); | 199 win_result = ::GetLastError(); |
| 202 TerminateTarget(&process_info); | 200 ::TerminateProcess(process_info.process_handle(), 0); |
| 203 return win_result; | 201 return win_result; |
| 204 } | 202 } |
| 205 | 203 |
| 206 sandbox_process_ = process_info.hProcess; | 204 sandbox_process_ = process_info.process_handle(); |
| 207 sandbox_thread_ = process_info.hThread; | 205 sandbox_thread_ = process_info.thread_handle(); |
| 208 sandbox_process_id_ = process_info.dwProcessId; | 206 sandbox_process_id_ = process_info.process_id(); |
| 209 | 207 |
| 210 #if defined(_WIN64) | 208 #if defined(_WIN64) |
| 211 void* entry_point = reinterpret_cast<void*>(context.Rcx); | 209 void* entry_point = reinterpret_cast<void*>(context.Rcx); |
| 212 #else | 210 #else |
| 213 #pragma warning(push) | 211 #pragma warning(push) |
| 214 #pragma warning(disable: 4312) | 212 #pragma warning(disable: 4312) |
| 215 // This cast generates a warning because it is 32 bit specific. | 213 // This cast generates a warning because it is 32 bit specific. |
| 216 void* entry_point = reinterpret_cast<void*>(context.Eax); | 214 void* entry_point = reinterpret_cast<void*>(context.Eax); |
| 217 #pragma warning(pop) | 215 #pragma warning(pop) |
| 218 #endif // _WIN64 | 216 #endif // _WIN64 |
| 219 base_address_ = GetBaseAddress(exe_path, entry_point); | 217 base_address_ = GetBaseAddress(exe_path, entry_point); |
| 220 *target_info = process_info; | 218 *target_info = process_info.Take(); |
|
alexeypa (please no reviews)
2012/03/29 04:51:35
This is an example where Swap semantic could be cl
erikwright (departed)
2012/03/30 17:30:27
See http://codereview.chromium.org/9959018/diff/20
| |
| 221 return win_result; | 219 return win_result; |
| 222 } | 220 } |
| 223 | 221 |
| 224 ResultCode TargetProcess::TransferVariable(char* name, void* address, | 222 ResultCode TargetProcess::TransferVariable(char* name, void* address, |
| 225 size_t size) { | 223 size_t size) { |
| 226 if (NULL == sandbox_process_) | 224 if (NULL == sandbox_process_) |
| 227 return SBOX_ERROR_UNEXPECTED_CALL; | 225 return SBOX_ERROR_UNEXPECTED_CALL; |
| 228 | 226 |
| 229 void* child_var = address; | 227 void* child_var = address; |
| 230 | 228 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 | 341 |
| 344 | 342 |
| 345 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { | 343 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { |
| 346 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); | 344 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); |
| 347 target->sandbox_process_ = process; | 345 target->sandbox_process_ = process; |
| 348 target->base_address_ = base_address; | 346 target->base_address_ = base_address; |
| 349 return target; | 347 return target; |
| 350 } | 348 } |
| 351 | 349 |
| 352 } // namespace sandbox | 350 } // namespace sandbox |
| OLD | NEW |