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/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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 | 266 |
| 267 NOTREACHED(); | 267 NOTREACHED(); |
| 268 return 0; | 268 return 0; |
| 269 } | 269 } |
| 270 | 270 |
| 271 // SpawnTarget does all the interesting sandbox setup and creates the target | 271 // SpawnTarget does all the interesting sandbox setup and creates the target |
| 272 // process inside the sandbox. | 272 // process inside the sandbox. |
| 273 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, | 273 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, |
| 274 const wchar_t* command_line, | 274 const wchar_t* command_line, |
| 275 TargetPolicy* policy, | 275 TargetPolicy* policy, |
| 276 ResultCode* last_warning, | |
| 276 PROCESS_INFORMATION* target_info) { | 277 PROCESS_INFORMATION* target_info) { |
| 277 if (!exe_path) | 278 if (!exe_path) |
| 278 return SBOX_ERROR_BAD_PARAMS; | 279 return SBOX_ERROR_BAD_PARAMS; |
| 279 | 280 |
| 280 if (!policy) | 281 if (!policy) |
| 281 return SBOX_ERROR_BAD_PARAMS; | 282 return SBOX_ERROR_BAD_PARAMS; |
| 282 | 283 |
| 283 // Even though the resources touched by SpawnTarget can be accessed in | 284 // Even though the resources touched by SpawnTarget can be accessed in |
| 284 // multiple threads, the method itself cannot be called from more than | 285 // 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 | 286 // 1 thread. This is to protect the global variables used while setting up |
| 286 // the child process. | 287 // the child process. |
| 287 static DWORD thread_id = ::GetCurrentThreadId(); | 288 static DWORD thread_id = ::GetCurrentThreadId(); |
| 288 DCHECK(thread_id == ::GetCurrentThreadId()); | 289 DCHECK(thread_id == ::GetCurrentThreadId()); |
| 290 *last_warning = SBOX_ALL_OK; | |
| 289 | 291 |
| 290 AutoLock lock(&lock_); | 292 AutoLock lock(&lock_); |
| 291 | 293 |
| 292 // This downcast is safe as long as we control CreatePolicy() | 294 // This downcast is safe as long as we control CreatePolicy() |
| 293 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); | 295 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); |
| 294 | 296 |
| 295 // Construct the tokens and the job object that we are going to associate | 297 // Construct the tokens and the job object that we are going to associate |
| 296 // with the soon to be created target process. | 298 // with the soon to be created target process. |
| 297 base::win::ScopedHandle initial_token; | 299 base::win::ScopedHandle initial_token; |
| 298 base::win::ScopedHandle lockdown_token; | 300 base::win::ScopedHandle lockdown_token; |
| 299 base::win::ScopedHandle lowbox_token; | 301 base::win::ScopedHandle lowbox_token; |
| 300 ResultCode result = SBOX_ALL_OK; | 302 ResultCode result = SBOX_ALL_OK; |
| 301 | 303 |
| 302 result = | 304 result = |
| 303 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); | 305 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); |
| 304 if (SBOX_ALL_OK != result) | 306 if (SBOX_ALL_OK != result) |
| 305 return result; | 307 return result; |
| 308 if (lowbox_token.IsValid() && | |
| 309 base::win::GetVersion() < base::win::VERSION_WIN8) { | |
| 310 // We don't allow lowbox_token below Windows 8. | |
| 311 return SBOX_ERROR_BAD_PARAMS; | |
| 312 } | |
| 306 | 313 |
| 307 base::win::ScopedHandle job; | 314 base::win::ScopedHandle job; |
| 308 result = policy_base->MakeJobObject(&job); | 315 result = policy_base->MakeJobObject(&job); |
| 309 if (SBOX_ALL_OK != result) | 316 if (SBOX_ALL_OK != result) |
| 310 return result; | 317 return result; |
| 311 | 318 |
| 312 // Initialize the startup information from the policy. | 319 // Initialize the startup information from the policy. |
| 313 base::win::StartupInformation startup_info; | 320 base::win::StartupInformation startup_info; |
| 314 // The liftime of |mitigations|, |inherit_handle_list| and | 321 // The liftime of |mitigations|, |inherit_handle_list| and |
| 315 // |child_process_creation| have to be at least as long as | 322 // |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. | 407 // Construct the thread pool here in case it is expensive. |
| 401 // The thread pool is shared by all the targets | 408 // The thread pool is shared by all the targets |
| 402 if (NULL == thread_pool_) | 409 if (NULL == thread_pool_) |
| 403 thread_pool_ = new Win2kThreadPool(); | 410 thread_pool_ = new Win2kThreadPool(); |
| 404 | 411 |
| 405 // Create the TargetProcess object and spawn the target suspended. Note that | 412 // 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. | 413 // Brokerservices does not own the target object. It is owned by the Policy. |
| 407 base::win::ScopedProcessInformation process_info; | 414 base::win::ScopedProcessInformation process_info; |
| 408 TargetProcess* target = | 415 TargetProcess* target = |
| 409 new TargetProcess(std::move(initial_token), std::move(lockdown_token), | 416 new TargetProcess(std::move(initial_token), std::move(lockdown_token), |
| 410 std::move(lowbox_token), job.Get(), thread_pool_); | 417 job.Get(), thread_pool_); |
| 411 | 418 |
| 412 DWORD win_result; | 419 DWORD win_result; |
| 413 result = target->Create(exe_path, command_line, inherit_handles, startup_info, | 420 result = target->Create(exe_path, command_line, inherit_handles, startup_info, |
| 414 &process_info, &win_result); | 421 &process_info, &win_result); |
| 415 | 422 |
| 416 if (result != SBOX_ALL_OK) { | 423 if (result != SBOX_ALL_OK) { |
| 417 SpawnCleanup(target, win_result); | 424 SpawnCleanup(target, win_result); |
| 418 return result; | 425 return result; |
| 419 } | 426 } |
| 420 | 427 |
| 428 if (lowbox_token.IsValid()) { | |
|
Will Harris
2016/07/12 16:10:59
comment here on why this does not abort
| |
| 429 *last_warning = target->AssignLowBoxToken(lowbox_token); | |
| 430 if (*last_warning != SBOX_ALL_OK) | |
| 431 win_result = ::GetLastError(); | |
| 432 } | |
| 433 | |
| 421 // Now the policy is the owner of the target. | 434 // Now the policy is the owner of the target. |
| 422 result = policy_base->AddTarget(target); | 435 result = policy_base->AddTarget(target); |
| 423 | 436 |
| 424 if (result != SBOX_ALL_OK) { | 437 if (result != SBOX_ALL_OK) { |
| 425 SpawnCleanup(target, 0); | 438 SpawnCleanup(target, 0); |
| 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. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 444 child_process_ids_.insert(process_info.process_id()); | 457 child_process_ids_.insert(process_info.process_id()); |
| 445 } else { | 458 } else { |
| 446 // We have to signal the event once here because the completion port will | 459 // We have to signal the event once here because the completion port will |
| 447 // never get a message that this target is being terminated thus we should | 460 // never get a message that this target is being terminated thus we should |
| 448 // not block WaitForAllTargets until we have at least one target with job. | 461 // not block WaitForAllTargets until we have at least one target with job. |
| 449 if (child_process_ids_.empty()) | 462 if (child_process_ids_.empty()) |
| 450 ::SetEvent(no_targets_.Get()); | 463 ::SetEvent(no_targets_.Get()); |
| 451 } | 464 } |
| 452 | 465 |
| 453 *target_info = process_info.Take(); | 466 *target_info = process_info.Take(); |
| 467 if (*last_warning != SBOX_ALL_OK) | |
| 468 ::SetLastError(win_result); | |
| 454 return result; | 469 return result; |
| 455 } | 470 } |
| 456 | 471 |
| 457 | 472 |
| 458 ResultCode BrokerServicesBase::WaitForAllTargets() { | 473 ResultCode BrokerServicesBase::WaitForAllTargets() { |
| 459 ::WaitForSingleObject(no_targets_.Get(), INFINITE); | 474 ::WaitForSingleObject(no_targets_.Get(), INFINITE); |
| 460 return SBOX_ALL_OK; | 475 return SBOX_ALL_OK; |
| 461 } | 476 } |
| 462 | 477 |
| 463 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { | 478 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
| 464 AutoLock lock(&lock_); | 479 AutoLock lock(&lock_); |
| 465 return child_process_ids_.find(process_id) != child_process_ids_.end(); | 480 return child_process_ids_.find(process_id) != child_process_ids_.end(); |
| 466 } | 481 } |
| 467 | 482 |
| 468 } // namespace sandbox | 483 } // namespace sandbox |
| OLD | NEW |