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/broker_services.h" | 5 #include "sandbox/src/broker_services.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/threading/platform_thread.h" | 9 #include "base/threading/platform_thread.h" |
| 10 #include "base/win/scoped_handle.h" | 10 #include "base/win/scoped_handle.h" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 } | 38 } |
| 39 | 39 |
| 40 // the different commands that you can send to the worker thread that | 40 // the different commands that you can send to the worker thread that |
| 41 // executes TargetEventsThread(). | 41 // executes TargetEventsThread(). |
| 42 enum { | 42 enum { |
| 43 THREAD_CTRL_NONE, | 43 THREAD_CTRL_NONE, |
| 44 THREAD_CTRL_QUIT, | 44 THREAD_CTRL_QUIT, |
| 45 THREAD_CTRL_LAST | 45 THREAD_CTRL_LAST |
| 46 }; | 46 }; |
| 47 | 47 |
| 48 } | 48 // Helper structure that allows the Broker to associate a job notification |
| 49 // with a job object and with a policy. | |
| 50 struct JobTracker { | |
| 51 HANDLE job; | |
| 52 sandbox::PolicyBase* policy; | |
| 53 JobTracker(HANDLE cjob, sandbox::PolicyBase* cpolicy) | |
| 54 : job(cjob), policy(cpolicy) { | |
| 55 } | |
| 56 }; | |
| 57 | |
| 58 // Helper structure that allows the broker to track peer processes | |
| 59 struct PeerTracker { | |
| 60 HANDLE wait_object_; | |
| 61 base::win::ScopedHandle process_; | |
| 62 PeerTracker() : wait_object_(NULL) { | |
| 63 } | |
| 64 }; | |
| 65 | |
| 66 } // namespace | |
| 49 | 67 |
| 50 namespace sandbox { | 68 namespace sandbox { |
| 51 | 69 |
| 52 BrokerServicesBase::BrokerServicesBase() | 70 BrokerServicesBase::BrokerServicesBase() |
| 53 : thread_pool_(NULL), job_port_(NULL), no_targets_(NULL), | 71 : thread_pool_(NULL), job_port_(NULL), no_targets_(NULL), |
| 54 job_thread_(NULL) { | 72 job_thread_(NULL) { |
| 55 } | 73 } |
| 56 | 74 |
| 57 // The broker uses a dedicated worker thread that services the job completion | 75 // The broker uses a dedicated worker thread that services the job completion |
| 58 // port to perform policy notifications and associated cleanup tasks. | 76 // port to perform policy notifications and associated cleanup tasks. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 78 | 96 |
| 79 // The destructor should only be called when the Broker process is terminating. | 97 // The destructor should only be called when the Broker process is terminating. |
| 80 // Since BrokerServicesBase is a singleton, this is called from the CRT | 98 // Since BrokerServicesBase is a singleton, this is called from the CRT |
| 81 // termination handlers, if this code lives on a DLL it is called during | 99 // termination handlers, if this code lives on a DLL it is called during |
| 82 // DLL_PROCESS_DETACH in other words, holding the loader lock, so we cannot | 100 // DLL_PROCESS_DETACH in other words, holding the loader lock, so we cannot |
| 83 // wait for threads here. | 101 // wait for threads here. |
| 84 BrokerServicesBase::~BrokerServicesBase() { | 102 BrokerServicesBase::~BrokerServicesBase() { |
| 85 // If there is no port Init() was never called successfully. | 103 // If there is no port Init() was never called successfully. |
| 86 if (!job_port_) | 104 if (!job_port_) |
| 87 return; | 105 return; |
| 106 | |
| 107 { // Cancel the wait events for all the peers. | |
| 108 AutoLock lock(&lock_); | |
| 109 for (PeerTrackerMap::iterator it = peer_map_.begin(); | |
| 110 it != peer_map_.end(); ++it) { | |
| 111 ::UnregisterWaitEx(it->second->wait_object_, NULL); | |
| 112 delete it->second; | |
| 113 } | |
| 114 } | |
|
cpu_(ooo_6.6-7.5)
2012/04/12 02:17:52
sounds like you want peer_map.clear() after 113 so
jschuh
2012/04/12 03:04:23
Oops. Looks like I accidentally dropped the "erase
| |
| 115 | |
| 88 // Closing the port causes, that no more Job notifications are delivered to | 116 // Closing the port causes, that no more Job notifications are delivered to |
| 89 // the worker thread and also causes the thread to exit. This is what we | 117 // the worker thread and also causes the thread to exit. This is what we |
| 90 // want to do since we are going to close all outstanding Jobs and notifying | 118 // want to do since we are going to close all outstanding Jobs and notifying |
| 91 // the policy objects ourselves. | 119 // the policy objects ourselves. |
| 92 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE); | 120 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE); |
| 93 ::CloseHandle(job_port_); | 121 ::CloseHandle(job_port_); |
| 94 | 122 |
| 95 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) { | 123 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) { |
| 96 // Cannot clean broker services. | 124 // Cannot clean broker services. |
| 97 NOTREACHED(); | 125 NOTREACHED(); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 305 } | 333 } |
| 306 | 334 |
| 307 | 335 |
| 308 ResultCode BrokerServicesBase::WaitForAllTargets() { | 336 ResultCode BrokerServicesBase::WaitForAllTargets() { |
| 309 ::WaitForSingleObject(no_targets_, INFINITE); | 337 ::WaitForSingleObject(no_targets_, INFINITE); |
| 310 return SBOX_ALL_OK; | 338 return SBOX_ALL_OK; |
| 311 } | 339 } |
| 312 | 340 |
| 313 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { | 341 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
| 314 AutoLock lock(&lock_); | 342 AutoLock lock(&lock_); |
| 315 return child_process_ids_.find(process_id) != child_process_ids_.end(); | 343 return child_process_ids_.find(process_id) != child_process_ids_.end() || |
| 344 peer_map_.find(process_id) != peer_map_.end(); | |
| 345 } | |
| 346 | |
| 347 VOID CALLBACK BrokerServicesBase::RemovePeerData(PVOID parameter, BOOLEAN) { | |
| 348 DWORD process_id = reinterpret_cast<DWORD>(parameter); | |
| 349 BrokerServicesBase* broker = BrokerServicesBase::GetInstance(); | |
| 350 | |
| 351 AutoLock lock(&broker->lock_); | |
| 352 PeerTrackerMap::iterator it = broker->peer_map_.find(process_id); | |
| 353 // Failure means we're shutting down, and the destructor will clean up. | |
| 354 if (::UnregisterWaitEx(it->second->wait_object_, NULL)) { | |
| 355 broker->peer_map_.erase(it); | |
| 356 delete it->second; | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) { | |
| 361 DWORD process_id = ::GetProcessId(peer_process); | |
| 362 if (!process_id) | |
| 363 return SBOX_ERROR_GENERIC; | |
| 364 | |
| 365 scoped_ptr<PeerTracker> peer(new PeerTracker); | |
| 366 if (!::DuplicateHandle(::GetCurrentProcess(), peer_process, | |
| 367 ::GetCurrentProcess(), peer->process_.Receive(), | |
| 368 SYNCHRONIZE, FALSE, 0)) { | |
| 369 return SBOX_ERROR_GENERIC; | |
| 370 } | |
| 371 | |
| 372 AutoLock lock(&lock_); | |
| 373 if (!peer_map_.insert(std::make_pair(process_id, peer.get())).second) | |
| 374 return SBOX_ERROR_BAD_PARAMS; | |
| 375 | |
| 376 if (!::RegisterWaitForSingleObject(&peer->wait_object_, | |
| 377 peer->process_, RemovePeerData, | |
| 378 reinterpret_cast<void*>(process_id), | |
| 379 INFINITE, WT_EXECUTEONLYONCE)) { | |
| 380 peer_map_.erase(process_id); | |
| 381 return SBOX_ERROR_GENERIC; | |
| 382 } | |
| 383 | |
| 384 // Leak the pointer since it will be cleaned up by the callback. | |
| 385 peer.release(); | |
| 386 return SBOX_ALL_OK; | |
| 316 } | 387 } |
| 317 | 388 |
| 318 } // namespace sandbox | 389 } // namespace sandbox |
| OLD | NEW |