| 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 |