| 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/broker_services.h" | 5 #include "sandbox/win/src/broker_services.h" |
| 6 | 6 |
| 7 #include <AclAPI.h> | 7 #include <AclAPI.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // Utility function to associate a completion port to a job object. | 30 // Utility function to associate a completion port to a job object. |
| 31 bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) { | 31 bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) { |
| 32 JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_acp = { key, port }; | 32 JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_acp = { key, port }; |
| 33 return ::SetInformationJobObject(job, | 33 return ::SetInformationJobObject(job, |
| 34 JobObjectAssociateCompletionPortInformation, | 34 JobObjectAssociateCompletionPortInformation, |
| 35 &job_acp, sizeof(job_acp))? true : false; | 35 &job_acp, sizeof(job_acp))? true : false; |
| 36 } | 36 } |
| 37 | 37 |
| 38 // Utility function to do the cleanup necessary when something goes wrong | 38 // Utility function to do the cleanup necessary when something goes wrong |
| 39 // while in SpawnTarget and we must terminate the target process. | 39 // while in SpawnTarget and we must terminate the target process. |
| 40 sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target, DWORD error) { | 40 sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target) { |
| 41 if (0 == error) | |
| 42 error = ::GetLastError(); | |
| 43 | |
| 44 target->Terminate(); | 41 target->Terminate(); |
| 45 delete target; | 42 delete target; |
| 46 ::SetLastError(error); | |
| 47 return sandbox::SBOX_ERROR_GENERIC; | 43 return sandbox::SBOX_ERROR_GENERIC; |
| 48 } | 44 } |
| 49 | 45 |
| 50 // the different commands that you can send to the worker thread that | 46 // the different commands that you can send to the worker thread that |
| 51 // executes TargetEventsThread(). | 47 // executes TargetEventsThread(). |
| 52 enum { | 48 enum { |
| 53 THREAD_CTRL_NONE, | 49 THREAD_CTRL_NONE, |
| 54 THREAD_CTRL_QUIT, | 50 THREAD_CTRL_QUIT, |
| 55 THREAD_CTRL_LAST, | 51 THREAD_CTRL_LAST, |
| 56 }; | 52 }; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 | 262 |
| 267 NOTREACHED(); | 263 NOTREACHED(); |
| 268 return 0; | 264 return 0; |
| 269 } | 265 } |
| 270 | 266 |
| 271 // SpawnTarget does all the interesting sandbox setup and creates the target | 267 // SpawnTarget does all the interesting sandbox setup and creates the target |
| 272 // process inside the sandbox. | 268 // process inside the sandbox. |
| 273 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, | 269 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, |
| 274 const wchar_t* command_line, | 270 const wchar_t* command_line, |
| 275 TargetPolicy* policy, | 271 TargetPolicy* policy, |
| 272 ResultCode* last_warning, |
| 273 DWORD* last_error, |
| 276 PROCESS_INFORMATION* target_info) { | 274 PROCESS_INFORMATION* target_info) { |
| 277 if (!exe_path) | 275 if (!exe_path) |
| 278 return SBOX_ERROR_BAD_PARAMS; | 276 return SBOX_ERROR_BAD_PARAMS; |
| 279 | 277 |
| 280 if (!policy) | 278 if (!policy) |
| 281 return SBOX_ERROR_BAD_PARAMS; | 279 return SBOX_ERROR_BAD_PARAMS; |
| 282 | 280 |
| 283 // Even though the resources touched by SpawnTarget can be accessed in | 281 // Even though the resources touched by SpawnTarget can be accessed in |
| 284 // multiple threads, the method itself cannot be called from more than | 282 // multiple threads, the method itself cannot be called from more than |
| 285 // 1 thread. This is to protect the global variables used while setting up | 283 // 1 thread. This is to protect the global variables used while setting up |
| 286 // the child process. | 284 // the child process. |
| 287 static DWORD thread_id = ::GetCurrentThreadId(); | 285 static DWORD thread_id = ::GetCurrentThreadId(); |
| 288 DCHECK(thread_id == ::GetCurrentThreadId()); | 286 DCHECK(thread_id == ::GetCurrentThreadId()); |
| 287 *last_warning = SBOX_ALL_OK; |
| 289 | 288 |
| 290 AutoLock lock(&lock_); | 289 AutoLock lock(&lock_); |
| 291 | 290 |
| 292 // This downcast is safe as long as we control CreatePolicy() | 291 // This downcast is safe as long as we control CreatePolicy() |
| 293 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); | 292 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); |
| 294 | 293 |
| 295 // Construct the tokens and the job object that we are going to associate | 294 // Construct the tokens and the job object that we are going to associate |
| 296 // with the soon to be created target process. | 295 // with the soon to be created target process. |
| 297 base::win::ScopedHandle initial_token; | 296 base::win::ScopedHandle initial_token; |
| 298 base::win::ScopedHandle lockdown_token; | 297 base::win::ScopedHandle lockdown_token; |
| 299 base::win::ScopedHandle lowbox_token; | 298 base::win::ScopedHandle lowbox_token; |
| 300 ResultCode result = SBOX_ALL_OK; | 299 ResultCode result = SBOX_ALL_OK; |
| 301 | 300 |
| 302 result = | 301 result = |
| 303 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); | 302 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); |
| 304 if (SBOX_ALL_OK != result) | 303 if (SBOX_ALL_OK != result) |
| 305 return result; | 304 return result; |
| 305 if (lowbox_token.IsValid() && |
| 306 base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 307 // We don't allow lowbox_token below Windows 8. |
| 308 return SBOX_ERROR_BAD_PARAMS; |
| 309 } |
| 306 | 310 |
| 307 base::win::ScopedHandle job; | 311 base::win::ScopedHandle job; |
| 308 result = policy_base->MakeJobObject(&job); | 312 result = policy_base->MakeJobObject(&job); |
| 309 if (SBOX_ALL_OK != result) | 313 if (SBOX_ALL_OK != result) |
| 310 return result; | 314 return result; |
| 311 | 315 |
| 312 // Initialize the startup information from the policy. | 316 // Initialize the startup information from the policy. |
| 313 base::win::StartupInformation startup_info; | 317 base::win::StartupInformation startup_info; |
| 314 // The liftime of |mitigations|, |inherit_handle_list| and | 318 // The liftime of |mitigations|, |inherit_handle_list| and |
| 315 // |child_process_creation| have to be at least as long as | 319 // |child_process_creation| have to be at least as long as |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 // Construct the thread pool here in case it is expensive. | 404 // Construct the thread pool here in case it is expensive. |
| 401 // The thread pool is shared by all the targets | 405 // The thread pool is shared by all the targets |
| 402 if (NULL == thread_pool_) | 406 if (NULL == thread_pool_) |
| 403 thread_pool_ = new Win2kThreadPool(); | 407 thread_pool_ = new Win2kThreadPool(); |
| 404 | 408 |
| 405 // Create the TargetProcess object and spawn the target suspended. Note that | 409 // Create the TargetProcess object and spawn the target suspended. Note that |
| 406 // Brokerservices does not own the target object. It is owned by the Policy. | 410 // Brokerservices does not own the target object. It is owned by the Policy. |
| 407 base::win::ScopedProcessInformation process_info; | 411 base::win::ScopedProcessInformation process_info; |
| 408 TargetProcess* target = | 412 TargetProcess* target = |
| 409 new TargetProcess(std::move(initial_token), std::move(lockdown_token), | 413 new TargetProcess(std::move(initial_token), std::move(lockdown_token), |
| 410 std::move(lowbox_token), job.Get(), thread_pool_); | 414 job.Get(), thread_pool_); |
| 411 | 415 |
| 412 DWORD win_result; | |
| 413 result = target->Create(exe_path, command_line, inherit_handles, startup_info, | 416 result = target->Create(exe_path, command_line, inherit_handles, startup_info, |
| 414 &process_info, &win_result); | 417 &process_info, last_error); |
| 415 | 418 |
| 416 if (result != SBOX_ALL_OK) { | 419 if (result != SBOX_ALL_OK) { |
| 417 SpawnCleanup(target, win_result); | 420 SpawnCleanup(target); |
| 418 return result; | 421 return result; |
| 419 } | 422 } |
| 420 | 423 |
| 424 if (lowbox_token.IsValid()) { |
| 425 *last_warning = target->AssignLowBoxToken(lowbox_token); |
| 426 // If this fails we continue, but report the error as a warning. |
| 427 // This is due to certain configurations causing the setting of the |
| 428 // token to fail post creation, and we'd rather continue if possible. |
| 429 if (*last_warning != SBOX_ALL_OK) |
| 430 *last_error = ::GetLastError(); |
| 431 } |
| 432 |
| 421 // Now the policy is the owner of the target. | 433 // Now the policy is the owner of the target. |
| 422 result = policy_base->AddTarget(target); | 434 result = policy_base->AddTarget(target); |
| 423 | 435 |
| 424 if (result != SBOX_ALL_OK) { | 436 if (result != SBOX_ALL_OK) { |
| 425 SpawnCleanup(target, 0); | 437 *last_error = ::GetLastError(); |
| 438 SpawnCleanup(target); |
| 426 return result; | 439 return result; |
| 427 } | 440 } |
| 428 | 441 |
| 429 // We are going to keep a pointer to the policy because we'll call it when | 442 // We are going to keep a pointer to the policy because we'll call it when |
| 430 // the job object generates notifications using the completion port. | 443 // the job object generates notifications using the completion port. |
| 431 policy_base->AddRef(); | 444 policy_base->AddRef(); |
| 432 if (job.IsValid()) { | 445 if (job.IsValid()) { |
| 433 std::unique_ptr<JobTracker> tracker( | 446 std::unique_ptr<JobTracker> tracker( |
| 434 new JobTracker(std::move(job), policy_base)); | 447 new JobTracker(std::move(job), policy_base)); |
| 435 | 448 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 459 ::WaitForSingleObject(no_targets_.Get(), INFINITE); | 472 ::WaitForSingleObject(no_targets_.Get(), INFINITE); |
| 460 return SBOX_ALL_OK; | 473 return SBOX_ALL_OK; |
| 461 } | 474 } |
| 462 | 475 |
| 463 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { | 476 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
| 464 AutoLock lock(&lock_); | 477 AutoLock lock(&lock_); |
| 465 return child_process_ids_.find(process_id) != child_process_ids_.end(); | 478 return child_process_ids_.find(process_id) != child_process_ids_.end(); |
| 466 } | 479 } |
| 467 | 480 |
| 468 } // namespace sandbox | 481 } // namespace sandbox |
| OLD | NEW |