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

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: switch back to start with refcount 1 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
« no previous file with comments | « sandbox/win/src/broker_services.h ('k') | sandbox/win/src/policy_target_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/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 scoped_refptr<TargetPolicy> policy(new PolicyBase);
149 // PolicyBase starts with refcount 1.
150 policy->Release();
151 return policy;
149 } 152 }
150 153
151 // The worker thread stays in a loop waiting for asynchronous notifications 154 // 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 155 // 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 156 // process on a job terminates, but in general this is the place to tell
154 // the policy about events. 157 // the policy about events.
155 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { 158 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
156 if (NULL == param) 159 if (NULL == param)
157 return 1; 160 return 1;
158 161
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } 264 }
262 265
263 NOTREACHED(); 266 NOTREACHED();
264 return 0; 267 return 0;
265 } 268 }
266 269
267 // SpawnTarget does all the interesting sandbox setup and creates the target 270 // SpawnTarget does all the interesting sandbox setup and creates the target
268 // process inside the sandbox. 271 // process inside the sandbox.
269 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, 272 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
270 const wchar_t* command_line, 273 const wchar_t* command_line,
271 TargetPolicy* policy, 274 scoped_refptr<TargetPolicy> policy,
272 ResultCode* last_warning, 275 ResultCode* last_warning,
273 DWORD* last_error, 276 DWORD* last_error,
274 PROCESS_INFORMATION* target_info) { 277 PROCESS_INFORMATION* target_info) {
275 if (!exe_path) 278 if (!exe_path)
276 return SBOX_ERROR_BAD_PARAMS; 279 return SBOX_ERROR_BAD_PARAMS;
277 280
278 if (!policy) 281 if (!policy)
279 return SBOX_ERROR_BAD_PARAMS; 282 return SBOX_ERROR_BAD_PARAMS;
280 283
281 // Even though the resources touched by SpawnTarget can be accessed in 284 // Even though the resources touched by SpawnTarget can be accessed in
282 // multiple threads, the method itself cannot be called from more than 285 // 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 286 // 1 thread. This is to protect the global variables used while setting up
284 // the child process. 287 // the child process.
285 static DWORD thread_id = ::GetCurrentThreadId(); 288 static DWORD thread_id = ::GetCurrentThreadId();
286 DCHECK(thread_id == ::GetCurrentThreadId()); 289 DCHECK(thread_id == ::GetCurrentThreadId());
287 *last_warning = SBOX_ALL_OK; 290 *last_warning = SBOX_ALL_OK;
288 291
289 AutoLock lock(&lock_); 292 AutoLock lock(&lock_);
290 293
291 // This downcast is safe as long as we control CreatePolicy() 294 // This downcast is safe as long as we control CreatePolicy()
292 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); 295 scoped_refptr<PolicyBase> policy_base(static_cast<PolicyBase*>(policy.get()));
293 296
294 // Construct the tokens and the job object that we are going to associate 297 // Construct the tokens and the job object that we are going to associate
295 // with the soon to be created target process. 298 // with the soon to be created target process.
296 base::win::ScopedHandle initial_token; 299 base::win::ScopedHandle initial_token;
297 base::win::ScopedHandle lockdown_token; 300 base::win::ScopedHandle lockdown_token;
298 base::win::ScopedHandle lowbox_token; 301 base::win::ScopedHandle lowbox_token;
299 ResultCode result = SBOX_ALL_OK; 302 ResultCode result = SBOX_ALL_OK;
300 303
301 result = 304 result =
302 policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); 305 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); 437 result = policy_base->AddTarget(target);
435 438
436 if (result != SBOX_ALL_OK) { 439 if (result != SBOX_ALL_OK) {
437 *last_error = ::GetLastError(); 440 *last_error = ::GetLastError();
438 SpawnCleanup(target); 441 SpawnCleanup(target);
439 return result; 442 return result;
440 } 443 }
441 444
442 // We are going to keep a pointer to the policy because we'll call it when 445 // 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. 446 // the job object generates notifications using the completion port.
444 policy_base->AddRef();
445 if (job.IsValid()) { 447 if (job.IsValid()) {
446 std::unique_ptr<JobTracker> tracker( 448 std::unique_ptr<JobTracker> tracker(
447 new JobTracker(std::move(job), policy_base)); 449 new JobTracker(std::move(job), policy_base));
448 450
449 // There is no obvious recovery after failure here. Previous version with 451 // There is no obvious recovery after failure here. Previous version with
450 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639 452 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
451 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), 453 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(),
452 tracker.get())); 454 tracker.get()));
453 455
454 // Save the tracker because in cleanup we might need to force closing 456 // Save the tracker because in cleanup we might need to force closing
(...skipping 17 matching lines...) Expand all
472 ::WaitForSingleObject(no_targets_.Get(), INFINITE); 474 ::WaitForSingleObject(no_targets_.Get(), INFINITE);
473 return SBOX_ALL_OK; 475 return SBOX_ALL_OK;
474 } 476 }
475 477
476 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { 478 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) {
477 AutoLock lock(&lock_); 479 AutoLock lock(&lock_);
478 return child_process_ids_.find(process_id) != child_process_ids_.end(); 480 return child_process_ids_.find(process_id) != child_process_ids_.end();
479 } 481 }
480 482
481 } // namespace sandbox 483 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/broker_services.h ('k') | sandbox/win/src/policy_target_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698