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 |