Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: sandbox/src/broker_services.cc

Issue 9960045: Add sandbox support for associating peer processes (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/src/broker_services.h ('k') | sandbox/src/handle_policy_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 23 matching lines...) Expand all
34 target->Terminate(); 34 target->Terminate();
35 delete target; 35 delete target;
36 ::SetLastError(error); 36 ::SetLastError(error);
37 return sandbox::SBOX_ERROR_GENERIC; 37 return sandbox::SBOX_ERROR_GENERIC;
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_REMOVE_PEER,
44 THREAD_CTRL_QUIT, 45 THREAD_CTRL_QUIT,
45 THREAD_CTRL_LAST 46 THREAD_CTRL_LAST,
46 }; 47 };
47 48
48 } 49 // Helper structure that allows the Broker to associate a job notification
50 // with a job object and with a policy.
51 struct JobTracker {
52 HANDLE job;
53 sandbox::PolicyBase* policy;
54 JobTracker(HANDLE cjob, sandbox::PolicyBase* cpolicy)
55 : job(cjob), policy(cpolicy) {
56 }
57 };
58
59 // Helper structure that allows the broker to track peer processes
60 struct PeerTracker {
61 HANDLE wait_object;
62 base::win::ScopedHandle process;
63 DWORD id;
64 HANDLE job_port;
65 PeerTracker(DWORD process_id, HANDLE broker_job_port)
66 : wait_object(NULL), id(process_id), job_port(broker_job_port) {
67 }
68 };
69
70 } // namespace
49 71
50 namespace sandbox { 72 namespace sandbox {
51 73
52 BrokerServicesBase::BrokerServicesBase() 74 BrokerServicesBase::BrokerServicesBase()
53 : thread_pool_(NULL), job_port_(NULL), no_targets_(NULL), 75 : thread_pool_(NULL), job_port_(NULL), no_targets_(NULL),
54 job_thread_(NULL) { 76 job_thread_(NULL) {
55 } 77 }
56 78
57 // The broker uses a dedicated worker thread that services the job completion 79 // The broker uses a dedicated worker thread that services the job completion
58 // port to perform policy notifications and associated cleanup tasks. 80 // port to perform policy notifications and associated cleanup tasks.
(...skipping 19 matching lines...) Expand all
78 100
79 // The destructor should only be called when the Broker process is terminating. 101 // The destructor should only be called when the Broker process is terminating.
80 // Since BrokerServicesBase is a singleton, this is called from the CRT 102 // 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 103 // 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 104 // DLL_PROCESS_DETACH in other words, holding the loader lock, so we cannot
83 // wait for threads here. 105 // wait for threads here.
84 BrokerServicesBase::~BrokerServicesBase() { 106 BrokerServicesBase::~BrokerServicesBase() {
85 // If there is no port Init() was never called successfully. 107 // If there is no port Init() was never called successfully.
86 if (!job_port_) 108 if (!job_port_)
87 return; 109 return;
110
88 // Closing the port causes, that no more Job notifications are delivered to 111 // 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 112 // 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 113 // want to do since we are going to close all outstanding Jobs and notifying
91 // the policy objects ourselves. 114 // the policy objects ourselves.
92 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE); 115 ::PostQueuedCompletionStatus(job_port_, 0, THREAD_CTRL_QUIT, FALSE);
93 ::CloseHandle(job_port_); 116 ::CloseHandle(job_port_);
94 117
95 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) { 118 if (WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_, 1000)) {
96 // Cannot clean broker services. 119 // Cannot clean broker services.
97 NOTREACHED(); 120 NOTREACHED();
98 return; 121 return;
99 } 122 }
100 123
101 JobTrackerList::iterator it; 124 JobTrackerList::iterator it;
102 for (it = tracker_list_.begin(); it != tracker_list_.end(); ++it) { 125 for (it = tracker_list_.begin(); it != tracker_list_.end(); ++it) {
103 JobTracker* tracker = (*it); 126 JobTracker* tracker = (*it);
104 FreeResources(tracker); 127 FreeResources(tracker);
105 delete tracker; 128 delete tracker;
106 } 129 }
107 ::CloseHandle(job_thread_); 130 ::CloseHandle(job_thread_);
108 delete thread_pool_; 131 delete thread_pool_;
109 ::CloseHandle(no_targets_); 132 ::CloseHandle(no_targets_);
133
134 // Cancel the wait events and delete remaining peer trackers.
135 for (PeerTrackerMap::iterator it = peer_map_.begin();
136 it != peer_map_.end(); ++it) {
137 // Deregistration shouldn't fail, but we leak rather than crash if it does.
138 if (::UnregisterWaitEx(it->second->wait_object, INVALID_HANDLE_VALUE)) {
139 delete it->second;
140 } else {
141 NOTREACHED();
142 }
143 }
144
110 // If job_port_ isn't NULL, assumes that the lock has been initialized. 145 // If job_port_ isn't NULL, assumes that the lock has been initialized.
111 if (job_port_) 146 if (job_port_)
112 ::DeleteCriticalSection(&lock_); 147 ::DeleteCriticalSection(&lock_);
113 } 148 }
114 149
115 TargetPolicy* BrokerServicesBase::CreatePolicy() { 150 TargetPolicy* BrokerServicesBase::CreatePolicy() {
116 // If you change the type of the object being created here you must also 151 // If you change the type of the object being created here you must also
117 // change the downcast to it in SpawnTarget(). 152 // change the downcast to it in SpawnTarget().
118 return new PolicyBase; 153 return new PolicyBase;
119 } 154 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: { 237 case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: {
203 break; 238 break;
204 } 239 }
205 240
206 default: { 241 default: {
207 NOTREACHED(); 242 NOTREACHED();
208 break; 243 break;
209 } 244 }
210 } 245 }
211 246
247 } else if (THREAD_CTRL_REMOVE_PEER == key) {
248 // Remove a process from our list of peers.
249 AutoLock lock(&broker->lock_);
250 PeerTrackerMap::iterator it =
251 broker->peer_map_.find(reinterpret_cast<DWORD>(ovl));
252 // This shouldn't fail, but if it does leak the memory rather than crash.
253 if (::UnregisterWaitEx(it->second->wait_object, INVALID_HANDLE_VALUE)) {
254 delete it->second;
255 broker->peer_map_.erase(it);
256 } else {
257 NOTREACHED();
258 }
259
212 } else if (THREAD_CTRL_QUIT == key) { 260 } else if (THREAD_CTRL_QUIT == key) {
213 // The broker object is being destroyed so the thread needs to exit. 261 // The broker object is being destroyed so the thread needs to exit.
214 return 0; 262 return 0;
263
215 } else { 264 } else {
216 // We have not implemented more commands. 265 // We have not implemented more commands.
217 NOTREACHED(); 266 NOTREACHED();
218 } 267 }
219 } 268 }
220 269
221 NOTREACHED(); 270 NOTREACHED();
222 return 0; 271 return 0;
223 } 272 }
224 273
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 } 354 }
306 355
307 356
308 ResultCode BrokerServicesBase::WaitForAllTargets() { 357 ResultCode BrokerServicesBase::WaitForAllTargets() {
309 ::WaitForSingleObject(no_targets_, INFINITE); 358 ::WaitForSingleObject(no_targets_, INFINITE);
310 return SBOX_ALL_OK; 359 return SBOX_ALL_OK;
311 } 360 }
312 361
313 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { 362 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) {
314 AutoLock lock(&lock_); 363 AutoLock lock(&lock_);
315 return child_process_ids_.find(process_id) != child_process_ids_.end(); 364 return child_process_ids_.find(process_id) != child_process_ids_.end() ||
365 peer_map_.find(process_id) != peer_map_.end();
366 }
367
368 VOID CALLBACK BrokerServicesBase::RemovePeer(PVOID parameter, BOOLEAN) {
369 PeerTracker* peer = reinterpret_cast<PeerTracker*>(parameter);
370 // Don't check the return code because we this may fail (safely) at shutdown.
371 ::PostQueuedCompletionStatus(peer->job_port, 0, THREAD_CTRL_REMOVE_PEER,
372 reinterpret_cast<LPOVERLAPPED>(peer->id));
373 }
374
375 ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
376 scoped_ptr<PeerTracker> peer(new PeerTracker(::GetProcessId(peer_process),
377 job_port_));
378 if (!peer->id)
379 return SBOX_ERROR_GENERIC;
380
381 if (!::DuplicateHandle(::GetCurrentProcess(), peer_process,
382 ::GetCurrentProcess(), peer->process.Receive(),
383 SYNCHRONIZE, FALSE, 0)) {
384 return SBOX_ERROR_GENERIC;
385 }
386
387 AutoLock lock(&lock_);
388 if (!peer_map_.insert(std::make_pair(peer->id, peer.get())).second)
389 return SBOX_ERROR_BAD_PARAMS;
390
391 if (!::RegisterWaitForSingleObject(&peer->wait_object,
392 peer->process, RemovePeer,
393 peer.get(), INFINITE, WT_EXECUTEONLYONCE |
394 WT_EXECUTEINWAITTHREAD)) {
395 peer_map_.erase(peer->id);
396 return SBOX_ERROR_GENERIC;
397 }
398
399 // Leak the pointer since it will be cleaned up by the callback.
400 peer.release();
401 return SBOX_ALL_OK;
316 } 402 }
317 403
318 } // namespace sandbox 404 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/src/broker_services.h ('k') | sandbox/src/handle_policy_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698