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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |