Chromium Code Reviews| Index: sandbox/src/broker_services.cc |
| =================================================================== |
| --- sandbox/src/broker_services.cc (revision 132034) |
| +++ sandbox/src/broker_services.cc (working copy) |
| @@ -42,11 +42,33 @@ |
| enum { |
| THREAD_CTRL_NONE, |
| THREAD_CTRL_QUIT, |
| - THREAD_CTRL_LAST |
| + THREAD_CTRL_REMOVE_PEER, |
|
cpu_(ooo_6.6-7.5)
2012/04/13 00:13:03
please leave ctrl_quit last.
jschuh
2012/04/13 00:25:43
Done.
|
| + THREAD_CTRL_LAST, |
| }; |
| -} |
| +// Helper structure that allows the Broker to associate a job notification |
| +// with a job object and with a policy. |
| +struct JobTracker { |
| + HANDLE job; |
| + sandbox::PolicyBase* policy; |
| + JobTracker(HANDLE cjob, sandbox::PolicyBase* cpolicy) |
| + : job(cjob), policy(cpolicy) { |
| + } |
| +}; |
| +// Helper structure that allows the broker to track peer processes |
| +struct PeerTracker { |
| + HANDLE wait_object_; |
| + base::win::ScopedHandle process_; |
| + DWORD id_; |
|
cpu_(ooo_6.6-7.5)
2012/04/13 00:13:03
remove the trailing underscores, it is a struct. T
jschuh
2012/04/13 00:25:43
Done.
|
| + HANDLE job_port_; |
| + PeerTracker(DWORD id, HANDLE job_port) |
| + : wait_object_(NULL), id_(id), job_port_(job_port) { |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| namespace sandbox { |
| BrokerServicesBase::BrokerServicesBase() |
| @@ -85,6 +107,7 @@ |
| // If there is no port Init() was never called successfully. |
| if (!job_port_) |
| return; |
| + |
| // Closing the port causes, that no more Job notifications are delivered to |
| // the worker thread and also causes the thread to exit. This is what we |
| // want to do since we are going to close all outstanding Jobs and notifying |
| @@ -107,6 +130,18 @@ |
| ::CloseHandle(job_thread_); |
| delete thread_pool_; |
| ::CloseHandle(no_targets_); |
| + |
| + // Cancel the wait events and delete remaining peer trackers. |
| + for (PeerTrackerMap::iterator it = peer_map_.begin(); |
| + it != peer_map_.end(); ++it) { |
| + // Deregistration shouldn't fail, but we leak rather than crash if it does. |
| + if (::UnregisterWaitEx(it->second->wait_object_, INVALID_HANDLE_VALUE)) { |
| + delete it->second; |
| + } else { |
| + NOTREACHED(); |
| + } |
| + } |
| + |
| // If job_port_ isn't NULL, assumes that the lock has been initialized. |
| if (job_port_) |
| ::DeleteCriticalSection(&lock_); |
| @@ -212,6 +247,20 @@ |
| } else if (THREAD_CTRL_QUIT == key) { |
| // The broker object is being destroyed so the thread needs to exit. |
|
cpu_(ooo_6.6-7.5)
2012/04/13 00:13:03
please move the THREAD_CTRL_QUIT to the end.
jschuh
2012/04/13 00:25:43
Done.
|
| return 0; |
| + |
| + } else if (THREAD_CTRL_REMOVE_PEER == key) { |
| + // Remove a process from our list of peers. |
| + AutoLock lock(&broker->lock_); |
| + PeerTrackerMap::iterator it = |
| + broker->peer_map_.find(reinterpret_cast<DWORD>(ovl)); |
| + // This shouldn't fail, but if it does leak the memory rather than crash. |
| + if (::UnregisterWaitEx(it->second->wait_object_, INVALID_HANDLE_VALUE)) { |
| + delete it->second; |
| + broker->peer_map_.erase(it); |
| + } else { |
| + NOTREACHED(); |
| + } |
| + |
| } else { |
| // We have not implemented more commands. |
| NOTREACHED(); |
| @@ -312,7 +361,44 @@ |
| bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
| AutoLock lock(&lock_); |
| - return child_process_ids_.find(process_id) != child_process_ids_.end(); |
| + return child_process_ids_.find(process_id) != child_process_ids_.end() || |
| + peer_map_.find(process_id) != peer_map_.end(); |
| } |
| +VOID CALLBACK BrokerServicesBase::RemovePeer(PVOID parameter, BOOLEAN) { |
| + PeerTracker* peer = reinterpret_cast<PeerTracker*>(parameter); |
| + // Don't check the return code because we this may fail (safely) at shutdown. |
| + ::PostQueuedCompletionStatus(peer->job_port_, 0, THREAD_CTRL_REMOVE_PEER, |
| + reinterpret_cast<LPOVERLAPPED>(peer->id_)); |
| +} |
| + |
| +ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) { |
| + scoped_ptr<PeerTracker> peer(new PeerTracker(::GetProcessId(peer_process), |
| + job_port_)); |
| + if (!peer->id_) |
| + return SBOX_ERROR_GENERIC; |
| + |
| + if (!::DuplicateHandle(::GetCurrentProcess(), peer_process, |
| + ::GetCurrentProcess(), peer->process_.Receive(), |
| + SYNCHRONIZE, FALSE, 0)) { |
| + return SBOX_ERROR_GENERIC; |
| + } |
| + |
| + AutoLock lock(&lock_); |
| + if (!peer_map_.insert(std::make_pair(peer->id_, peer.get())).second) |
| + return SBOX_ERROR_BAD_PARAMS; |
| + |
| + if (!::RegisterWaitForSingleObject(&peer->wait_object_, |
| + peer->process_, RemovePeer, |
| + peer.get(), INFINITE, WT_EXECUTEONLYONCE | |
| + WT_EXECUTEINWAITTHREAD)) { |
| + peer_map_.erase(peer->id_); |
| + return SBOX_ERROR_GENERIC; |
| + } |
| + |
| + // Leak the pointer since it will be cleaned up by the callback. |
| + peer.release(); |
| + return SBOX_ALL_OK; |
| +} |
| + |
| } // namespace sandbox |