| 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/win/src/target_process.h" | 5 #include "sandbox/win/src/target_process.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/debug/alias.h" | |
| 9 #include "base/debug/dump_without_crashing.h" | |
| 10 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/win/pe_image.h" | 9 #include "base/win/pe_image.h" |
| 12 #include "base/win/startup_information.h" | 10 #include "base/win/startup_information.h" |
| 13 #include "base/win/windows_version.h" | 11 #include "base/win/windows_version.h" |
| 14 #include "sandbox/win/src/crosscall_server.h" | 12 #include "sandbox/win/src/crosscall_server.h" |
| 15 #include "sandbox/win/src/crosscall_client.h" | 13 #include "sandbox/win/src/crosscall_client.h" |
| 16 #include "sandbox/win/src/policy_low_level.h" | 14 #include "sandbox/win/src/policy_low_level.h" |
| 17 #include "sandbox/win/src/sandbox_types.h" | 15 #include "sandbox/win/src/sandbox_types.h" |
| 18 #include "sandbox/win/src/sharedmem_ipc_server.h" | 16 #include "sandbox/win/src/sharedmem_ipc_server.h" |
| 19 #include "sandbox/win/src/win_utils.h" | 17 #include "sandbox/win/src/win_utils.h" |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 if (!::CreateProcess(exe_path, | 150 if (!::CreateProcess(exe_path, |
| 153 cmd_line.get(), | 151 cmd_line.get(), |
| 154 NULL, // No security attribute. | 152 NULL, // No security attribute. |
| 155 NULL, // No thread attribute. | 153 NULL, // No thread attribute. |
| 156 inherit_handles, | 154 inherit_handles, |
| 157 flags, | 155 flags, |
| 158 NULL, // Use the environment of the caller. | 156 NULL, // Use the environment of the caller. |
| 159 NULL, // Use current directory of the caller. | 157 NULL, // Use current directory of the caller. |
| 160 startup_info.startup_info(), | 158 startup_info.startup_info(), |
| 161 &temp_process_info)) { | 159 &temp_process_info)) { |
| 162 // TODO(shrikant): Remove following code once we gather some dumps for | |
| 163 // debugging appcontainer related failures (crbug.com/467920). | |
| 164 base::debug::Alias(exe_path); | |
| 165 base::debug::DumpWithoutCrashing(); | |
| 166 return ::GetLastError(); | 160 return ::GetLastError(); |
| 167 } | 161 } |
| 168 } else { | 162 } else { |
| 169 if (!::CreateProcessAsUserW(scoped_lockdown_token.Get(), | 163 if (!::CreateProcessAsUserW(scoped_lockdown_token.Get(), |
| 170 exe_path, | 164 exe_path, |
| 171 cmd_line.get(), | 165 cmd_line.get(), |
| 172 NULL, // No security attribute. | 166 NULL, // No security attribute. |
| 173 NULL, // No thread attribute. | 167 NULL, // No thread attribute. |
| 174 inherit_handles, | 168 inherit_handles, |
| 175 flags, | 169 flags, |
| 176 NULL, // Use the environment of the caller. | 170 NULL, // Use the environment of the caller. |
| 177 NULL, // Use current directory of the caller. | 171 NULL, // Use current directory of the caller. |
| 178 startup_info.startup_info(), | 172 startup_info.startup_info(), |
| 179 &temp_process_info)) { | 173 &temp_process_info)) { |
| 180 return ::GetLastError(); | 174 return ::GetLastError(); |
| 181 } | 175 } |
| 182 } | 176 } |
| 183 base::win::ScopedProcessInformation process_info(temp_process_info); | 177 base::win::ScopedProcessInformation process_info(temp_process_info); |
| 184 | 178 |
| 185 DWORD win_result = ERROR_SUCCESS; | 179 DWORD win_result = ERROR_SUCCESS; |
| 186 | 180 |
| 187 if (job_) { | 181 if (job_) { |
| 188 // Assign the suspended target to the windows job object. | 182 // Assign the suspended target to the windows job object. |
| 189 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { | 183 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { |
| 190 win_result = ::GetLastError(); | 184 win_result = ::GetLastError(); |
| 191 if (set_lockdown_token_after_create) { | |
| 192 // TODO(shrikant): Remove this code once we gather some dumps for | |
| 193 // debugging appcontainer related failures (crbug.com/467920). | |
| 194 base::debug::Alias(&win_result); | |
| 195 base::debug::DumpWithoutCrashing(); | |
| 196 } | |
| 197 ::TerminateProcess(process_info.process_handle(), 0); | 185 ::TerminateProcess(process_info.process_handle(), 0); |
| 198 return win_result; | 186 return win_result; |
| 199 } | 187 } |
| 200 } | 188 } |
| 201 | 189 |
| 202 if (initial_token_.IsValid()) { | 190 if (initial_token_.IsValid()) { |
| 203 // Change the token of the main thread of the new process for the | 191 // Change the token of the main thread of the new process for the |
| 204 // impersonation token with more rights. This allows the target to start; | 192 // impersonation token with more rights. This allows the target to start; |
| 205 // otherwise it will crash too early for us to help. | 193 // otherwise it will crash too early for us to help. |
| 206 HANDLE temp_thread = process_info.thread_handle(); | 194 HANDLE temp_thread = process_info.thread_handle(); |
| 207 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { | 195 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { |
| 208 win_result = ::GetLastError(); | 196 win_result = ::GetLastError(); |
| 209 if (set_lockdown_token_after_create) { | |
| 210 // TODO(shrikant): Remove this code once we gather some dumps for | |
| 211 // debugging appcontainer related failures (crbug.com/467920). | |
| 212 base::debug::Alias(&win_result); | |
| 213 base::debug::DumpWithoutCrashing(); | |
| 214 } | |
| 215 // It might be a security breach if we let the target run outside the job | 197 // It might be a security breach if we let the target run outside the job |
| 216 // so kill it before it causes damage. | 198 // so kill it before it causes damage. |
| 217 ::TerminateProcess(process_info.process_handle(), 0); | 199 ::TerminateProcess(process_info.process_handle(), 0); |
| 218 return win_result; | 200 return win_result; |
| 219 } | 201 } |
| 220 initial_token_.Close(); | 202 initial_token_.Close(); |
| 221 } | 203 } |
| 222 | 204 |
| 223 if (set_lockdown_token_after_create) { | 205 if (set_lockdown_token_after_create) { |
| 224 PROCESS_ACCESS_TOKEN process_access_token; | 206 PROCESS_ACCESS_TOKEN process_access_token; |
| 225 process_access_token.thread = process_info.thread_handle(); | 207 process_access_token.thread = process_info.thread_handle(); |
| 226 process_access_token.token = scoped_lockdown_token.Get(); | 208 process_access_token.token = scoped_lockdown_token.Get(); |
| 227 | 209 |
| 228 NtSetInformationProcess SetInformationProcess = NULL; | 210 NtSetInformationProcess SetInformationProcess = NULL; |
| 229 ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); | 211 ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); |
| 230 | 212 |
| 231 NTSTATUS status = SetInformationProcess( | 213 NTSTATUS status = SetInformationProcess( |
| 232 process_info.process_handle(), | 214 process_info.process_handle(), |
| 233 static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), | 215 static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), |
| 234 &process_access_token, | 216 &process_access_token, |
| 235 sizeof(process_access_token)); | 217 sizeof(process_access_token)); |
| 236 if (!NT_SUCCESS(status)) { | 218 if (!NT_SUCCESS(status)) { |
| 237 win_result = ::GetLastError(); | 219 win_result = ::GetLastError(); |
| 238 // TODO(shrikant): Remove this code once we gather some dumps for | |
| 239 // debugging appcontainer related failures (crbug.com/467920). | |
| 240 base::debug::Alias(&win_result); | |
| 241 base::debug::DumpWithoutCrashing(); | |
| 242 ::TerminateProcess(process_info.process_handle(), 0); // exit code | 220 ::TerminateProcess(process_info.process_handle(), 0); // exit code |
| 243 return win_result; | 221 return win_result; |
| 244 } | 222 } |
| 245 } | 223 } |
| 246 | 224 |
| 247 CONTEXT context; | 225 CONTEXT context; |
| 248 context.ContextFlags = CONTEXT_ALL; | 226 context.ContextFlags = CONTEXT_ALL; |
| 249 if (!::GetThreadContext(process_info.thread_handle(), &context)) { | 227 if (!::GetThreadContext(process_info.thread_handle(), &context)) { |
| 250 win_result = ::GetLastError(); | 228 win_result = ::GetLastError(); |
| 251 if (set_lockdown_token_after_create) { | |
| 252 // TODO(shrikant): Remove this code once we gather some dumps for | |
| 253 // debugging appcontainer related failures (crbug.com/467920). | |
| 254 base::debug::Alias(&win_result); | |
| 255 base::debug::DumpWithoutCrashing(); | |
| 256 } | |
| 257 ::TerminateProcess(process_info.process_handle(), 0); | 229 ::TerminateProcess(process_info.process_handle(), 0); |
| 258 return win_result; | 230 return win_result; |
| 259 } | 231 } |
| 260 | 232 |
| 261 #if defined(_WIN64) | 233 #if defined(_WIN64) |
| 262 void* entry_point = reinterpret_cast<void*>(context.Rcx); | 234 void* entry_point = reinterpret_cast<void*>(context.Rcx); |
| 263 #else | 235 #else |
| 264 #pragma warning(push) | 236 #pragma warning(push) |
| 265 #pragma warning(disable: 4312) | 237 #pragma warning(disable: 4312) |
| 266 // This cast generates a warning because it is 32 bit specific. | 238 // This cast generates a warning because it is 32 bit specific. |
| 267 void* entry_point = reinterpret_cast<void*>(context.Eax); | 239 void* entry_point = reinterpret_cast<void*>(context.Eax); |
| 268 #pragma warning(pop) | 240 #pragma warning(pop) |
| 269 #endif // _WIN64 | 241 #endif // _WIN64 |
| 270 | 242 |
| 271 if (!target_info->DuplicateFrom(process_info)) { | 243 if (!target_info->DuplicateFrom(process_info)) { |
| 272 win_result = ::GetLastError(); // This may or may not be correct. | 244 win_result = ::GetLastError(); // This may or may not be correct. |
| 273 if (set_lockdown_token_after_create) { | |
| 274 // TODO(shrikant): Remove this code once we gather some dumps for | |
| 275 // debugging appcontainer related failures (crbug.com/467920). | |
| 276 base::debug::Alias(&win_result); | |
| 277 base::debug::DumpWithoutCrashing(); | |
| 278 } | |
| 279 ::TerminateProcess(process_info.process_handle(), 0); | 245 ::TerminateProcess(process_info.process_handle(), 0); |
| 280 return win_result; | 246 return win_result; |
| 281 } | 247 } |
| 282 | 248 |
| 283 base_address_ = GetBaseAddress(exe_path, entry_point); | 249 base_address_ = GetBaseAddress(exe_path, entry_point); |
| 284 sandbox_process_info_.Set(process_info.Take()); | 250 sandbox_process_info_.Set(process_info.Take()); |
| 285 return win_result; | 251 return win_result; |
| 286 } | 252 } |
| 287 | 253 |
| 288 ResultCode TargetProcess::TransferVariable(const char* name, void* address, | 254 ResultCode TargetProcess::TransferVariable(const char* name, void* address, |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { | 376 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { |
| 411 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); | 377 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); |
| 412 PROCESS_INFORMATION process_info = {}; | 378 PROCESS_INFORMATION process_info = {}; |
| 413 process_info.hProcess = process; | 379 process_info.hProcess = process; |
| 414 target->sandbox_process_info_.Set(process_info); | 380 target->sandbox_process_info_.Set(process_info); |
| 415 target->base_address_ = base_address; | 381 target->base_address_ = base_address; |
| 416 return target; | 382 return target; |
| 417 } | 383 } |
| 418 | 384 |
| 419 } // namespace sandbox | 385 } // namespace sandbox |
| OLD | NEW |