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 |