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

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

Issue 2316333003: Fix sandbox::PolicyBase leak (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: avoid using RefCountedThreadSafe Created 4 years, 3 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
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/win/src/broker_services.h" 5 #include "sandbox/win/src/broker_services.h"
6 6
7 #include <AclAPI.h> 7 #include <AclAPI.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <memory> 10 #include <memory>
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 // executes TargetEventsThread(). 47 // executes TargetEventsThread().
48 enum { 48 enum {
49 THREAD_CTRL_NONE, 49 THREAD_CTRL_NONE,
50 THREAD_CTRL_QUIT, 50 THREAD_CTRL_QUIT,
51 THREAD_CTRL_LAST, 51 THREAD_CTRL_LAST,
52 }; 52 };
53 53
54 // Helper structure that allows the Broker to associate a job notification 54 // Helper structure that allows the Broker to associate a job notification
55 // with a job object and with a policy. 55 // with a job object and with a policy.
56 struct JobTracker { 56 struct JobTracker {
57 JobTracker(base::win::ScopedHandle job, sandbox::PolicyBase* policy) 57 JobTracker(base::win::ScopedHandle job,
58 scoped_refptr<sandbox::PolicyBase> policy)
58 : job(std::move(job)), policy(policy) {} 59 : job(std::move(job)), policy(policy) {}
59 ~JobTracker() { 60 ~JobTracker() {
60 FreeResources(); 61 FreeResources();
61 } 62 }
62 63
63 // Releases the Job and notifies the associated Policy object to release its 64 // Releases the Job and notifies the associated Policy object to release its
64 // resources as well. 65 // resources as well.
65 void FreeResources(); 66 void FreeResources();
66 67
67 base::win::ScopedHandle job; 68 base::win::ScopedHandle job;
68 sandbox::PolicyBase* policy; 69 scoped_refptr<sandbox::PolicyBase> policy;
69 }; 70 };
70 71
71 void JobTracker::FreeResources() { 72 void JobTracker::FreeResources() {
72 if (policy) { 73 if (policy) {
73 BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK); 74 BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK);
74 DCHECK(res); 75 DCHECK(res);
75 // Closing the job causes the target process to be destroyed so this needs 76 // Closing the job causes the target process to be destroyed so this needs
76 // to happen before calling OnJobEmpty(). 77 // to happen before calling OnJobEmpty().
77 HANDLE stale_job_handle = job.Get(); 78 HANDLE stale_job_handle = job.Get();
78 job.Close(); 79 job.Close();
79 80
80 // In OnJobEmpty() we don't actually use the job handle directly. 81 // In OnJobEmpty() we don't actually use the job handle directly.
81 policy->OnJobEmpty(stale_job_handle); 82 policy->OnJobEmpty(stale_job_handle);
82 policy->Release(); 83 policy = nullptr;
83 policy = NULL;
84 } 84 }
85 } 85 }
86 86
87 } // namespace 87 } // namespace
88 88
89 namespace sandbox { 89 namespace sandbox {
90 90
91 BrokerServicesBase::BrokerServicesBase() : thread_pool_(NULL) { 91 BrokerServicesBase::BrokerServicesBase() : thread_pool_(NULL) {
92 } 92 }
93 93
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 NOTREACHED(); 135 NOTREACHED();
136 return; 136 return;
137 } 137 }
138 138
139 base::STLDeleteElements(&tracker_list_); 139 base::STLDeleteElements(&tracker_list_);
140 delete thread_pool_; 140 delete thread_pool_;
141 141
142 ::DeleteCriticalSection(&lock_); 142 ::DeleteCriticalSection(&lock_);
143 } 143 }
144 144
145 TargetPolicy* BrokerServicesBase::CreatePolicy() { 145 scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() {
146 // If you change the type of the object being created here you must also 146 // If you change the type of the object being created here you must also
147 // change the downcast to it in SpawnTarget(). 147 // change the downcast to it in SpawnTarget().
148 return new PolicyBase; 148 return scoped_refptr<TargetPolicy>(new PolicyBase);
149 } 149 }
150 150
151 // The worker thread stays in a loop waiting for asynchronous notifications 151 // The worker thread stays in a loop waiting for asynchronous notifications
152 // from the job objects. Right now we only care about knowing when the last 152 // from the job objects. Right now we only care about knowing when the last
153 // process on a job terminates, but in general this is the place to tell 153 // process on a job terminates, but in general this is the place to tell
154 // the policy about events. 154 // the policy about events.
155 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { 155 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
156 if (NULL == param) 156 if (NULL == param)
157 return 1; 157 return 1;
158 158
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } 261 }
262 262
263 NOTREACHED(); 263 NOTREACHED();
264 return 0; 264 return 0;
265 } 265 }
266 266
267 // SpawnTarget does all the interesting sandbox setup and creates the target 267 // SpawnTarget does all the interesting sandbox setup and creates the target
268 // process inside the sandbox. 268 // process inside the sandbox.
269 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, 269 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
270 const wchar_t* command_line, 270 const wchar_t* command_line,
271 TargetPolicy* policy, 271 scoped_refptr<TargetPolicy> policy,
272 ResultCode* last_warning, 272 ResultCode* last_warning,
273 DWORD* last_error, 273 DWORD* last_error,
274 PROCESS_INFORMATION* target_info) { 274 PROCESS_INFORMATION* target_info) {
275 if (!exe_path) 275 if (!exe_path)
276 return SBOX_ERROR_BAD_PARAMS; 276 return SBOX_ERROR_BAD_PARAMS;
277 277
278 if (!policy) 278 if (!policy)
279 return SBOX_ERROR_BAD_PARAMS; 279 return SBOX_ERROR_BAD_PARAMS;
280 280
281 // Even though the resources touched by SpawnTarget can be accessed in 281 // Even though the resources touched by SpawnTarget can be accessed in
282 // multiple threads, the method itself cannot be called from more than 282 // multiple threads, the method itself cannot be called from more than
283 // 1 thread. This is to protect the global variables used while setting up 283 // 1 thread. This is to protect the global variables used while setting up
284 // the child process. 284 // the child process.
285 static DWORD thread_id = ::GetCurrentThreadId(); 285 static DWORD thread_id = ::GetCurrentThreadId();
286 DCHECK(thread_id == ::GetCurrentThreadId()); 286 DCHECK(thread_id == ::GetCurrentThreadId());
287 *last_warning = SBOX_ALL_OK; 287 *last_warning = SBOX_ALL_OK;
288 288
289 AutoLock lock(&lock_); 289 AutoLock lock(&lock_);
290 290
291 // This downcast is safe as long as we control CreatePolicy() 291 // This downcast is safe as long as we control CreatePolicy()
292 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); 292 scoped_refptr<PolicyBase> policy_base(static_cast<PolicyBase*>(policy.get()));
293 293
294 // Construct the tokens and the job object that we are going to associate 294 // Construct the tokens and the job object that we are going to associate
295 // with the soon to be created target process. 295 // with the soon to be created target process.
296 base::win::ScopedHandle initial_token; 296 base::win::ScopedHandle initial_token;
297 base::win::ScopedHandle lockdown_token; 297 base::win::ScopedHandle lockdown_token;
298 base::win::ScopedHandle lowbox_token; 298 base::win::ScopedHandle lowbox_token;
299 ResultCode result = SBOX_ALL_OK; 299 ResultCode result = SBOX_ALL_OK;
300 300
301 result = 301 result =
302 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); 302 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 result = policy_base->AddTarget(target); 434 result = policy_base->AddTarget(target);
435 435
436 if (result != SBOX_ALL_OK) { 436 if (result != SBOX_ALL_OK) {
437 *last_error = ::GetLastError(); 437 *last_error = ::GetLastError();
438 SpawnCleanup(target); 438 SpawnCleanup(target);
439 return result; 439 return result;
440 } 440 }
441 441
442 // We are going to keep a pointer to the policy because we'll call it when 442 // We are going to keep a pointer to the policy because we'll call it when
443 // the job object generates notifications using the completion port. 443 // the job object generates notifications using the completion port.
444 policy_base->AddRef();
445 if (job.IsValid()) { 444 if (job.IsValid()) {
446 std::unique_ptr<JobTracker> tracker( 445 std::unique_ptr<JobTracker> tracker(
447 new JobTracker(std::move(job), policy_base)); 446 new JobTracker(std::move(job), policy_base));
448 447
449 // There is no obvious recovery after failure here. Previous version with 448 // There is no obvious recovery after failure here. Previous version with
450 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639 449 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
451 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), 450 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(),
452 tracker.get())); 451 tracker.get()));
453 452
454 // Save the tracker because in cleanup we might need to force closing 453 // Save the tracker because in cleanup we might need to force closing
(...skipping 17 matching lines...) Expand all
472 ::WaitForSingleObject(no_targets_.Get(), INFINITE); 471 ::WaitForSingleObject(no_targets_.Get(), INFINITE);
473 return SBOX_ALL_OK; 472 return SBOX_ALL_OK;
474 } 473 }
475 474
476 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { 475 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) {
477 AutoLock lock(&lock_); 476 AutoLock lock(&lock_);
478 return child_process_ids_.find(process_id) != child_process_ids_.end(); 477 return child_process_ids_.find(process_id) != child_process_ids_.end();
479 } 478 }
480 479
481 } // namespace sandbox 480 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698