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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 // If there is no port Init() was never called successfully. | 85 // If there is no port Init() was never called successfully. |
86 if (!job_port_) | 86 if (!job_port_) |
87 return; | 87 return; |
88 // Closing the port causes, that no more Job notifications are delivered to | 88 // 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 | 89 // 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 | 90 // want to do since we are going to close all outstanding Jobs and notifying |
91 // the policy objects ourselves. | 91 // the policy objects ourselves. |
92 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE); | 92 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE); |
93 ::CloseHandle(job_port_); | 93 ::CloseHandle(job_port_); |
94 | 94 |
| 95 { // Cancel the wait events for all the peers. |
| 96 AutoLock lock(&lock_); |
| 97 for (PeerTrackerMap::iterator it = peer_map_.begin(); |
| 98 it != peer_map_.end(); ++it) { |
| 99 // This call terminates any running handlers. |
| 100 ::UnregisterWaitEx(it->second->wait_object_, NULL); |
| 101 delete it->second; |
| 102 } |
| 103 } |
| 104 |
95 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) { | 105 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) { |
96 // Cannot clean broker services. | 106 // Cannot clean broker services. |
97 NOTREACHED(); | 107 NOTREACHED(); |
98 return; | 108 return; |
99 } | 109 } |
100 | 110 |
101 JobTrackerList::iterator it; | 111 JobTrackerList::iterator it; |
102 for (it = tracker_list_.begin(); it != tracker_list_.end(); ++it) { | 112 for (it = tracker_list_.begin(); it != tracker_list_.end(); ++it) { |
103 JobTracker* tracker = (*it); | 113 JobTracker* tracker = (*it); |
104 FreeResources(tracker); | 114 FreeResources(tracker); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 } | 315 } |
306 | 316 |
307 | 317 |
308 ResultCode BrokerServicesBase::WaitForAllTargets() { | 318 ResultCode BrokerServicesBase::WaitForAllTargets() { |
309 ::WaitForSingleObject(no_targets_, INFINITE); | 319 ::WaitForSingleObject(no_targets_, INFINITE); |
310 return SBOX_ALL_OK; | 320 return SBOX_ALL_OK; |
311 } | 321 } |
312 | 322 |
313 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { | 323 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
314 AutoLock lock(&lock_); | 324 AutoLock lock(&lock_); |
315 return child_process_ids_.find(process_id) != child_process_ids_.end(); | 325 return child_process_ids_.find(process_id) != child_process_ids_.end() || |
| 326 peer_map_.find(process_id) != peer_map_.end(); |
| 327 } |
| 328 |
| 329 VOID CALLBACK BrokerServicesBase::RemovePeerData(PVOID parameter, BOOLEAN) { |
| 330 DWORD process_id = reinterpret_cast<DWORD>(parameter); |
| 331 BrokerServicesBase* broker = BrokerServicesBase::GetInstance(); |
| 332 PeerTracker* peer_data; |
| 333 |
| 334 { // Hold the lock only during removal (since UregisterWaitEx can block). |
| 335 AutoLock lock(&broker->lock_); |
| 336 PeerTrackerMap::iterator it = broker->peer_map_.find(process_id); |
| 337 peer_data = it->second; |
| 338 broker->peer_map_.erase(it); |
| 339 } |
| 340 |
| 341 HANDLE wait_object = peer_data->wait_object_; |
| 342 delete peer_data; |
| 343 // This prevents us from terminating our own running handler. |
| 344 ::UnregisterWaitEx(wait_object, INVALID_HANDLE_VALUE); |
| 345 } |
| 346 |
| 347 ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) { |
| 348 DWORD process_id = ::GetProcessId(peer_process); |
| 349 if (!process_id) |
| 350 return SBOX_ERROR_GENERIC; |
| 351 |
| 352 scoped_ptr<PeerTracker> peer(new PeerTracker); |
| 353 if (!::DuplicateHandle(::GetCurrentProcess(), peer_process, |
| 354 ::GetCurrentProcess(), peer->process_.Receive(), |
| 355 SYNCHRONIZE, FALSE, 0)) { |
| 356 return SBOX_ERROR_GENERIC; |
| 357 } |
| 358 |
| 359 AutoLock lock(&lock_); |
| 360 if (!peer_map_.insert(std::make_pair(process_id, peer.get())).second) |
| 361 return SBOX_ERROR_BAD_PARAMS; |
| 362 |
| 363 if (!::RegisterWaitForSingleObject(&peer->wait_object_, |
| 364 peer->process_, RemovePeerData, |
| 365 reinterpret_cast<void*>(process_id), |
| 366 INFINITE, WT_EXECUTEINWAITTHREAD | |
| 367 WT_EXECUTEONLYONCE)) { |
| 368 peer_map_.erase(process_id); |
| 369 return SBOX_ERROR_GENERIC; |
| 370 } |
| 371 |
| 372 // Leak the pointer since it will be cleaned up by the callback. |
| 373 peer.release(); |
| 374 return SBOX_ALL_OK; |
316 } | 375 } |
317 | 376 |
318 } // namespace sandbox | 377 } // namespace sandbox |
OLD | NEW |