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, | 57 JobTracker(base::win::ScopedHandle job, sandbox::PolicyBase* policy) |
58 scoped_refptr<sandbox::PolicyBase> policy) | |
59 : job(std::move(job)), policy(policy) {} | 58 : job(std::move(job)), policy(policy) {} |
60 ~JobTracker() { | 59 ~JobTracker() { |
61 FreeResources(); | 60 FreeResources(); |
62 } | 61 } |
63 | 62 |
64 // Releases the Job and notifies the associated Policy object to release its | 63 // Releases the Job and notifies the associated Policy object to release its |
65 // resources as well. | 64 // resources as well. |
66 void FreeResources(); | 65 void FreeResources(); |
67 | 66 |
68 base::win::ScopedHandle job; | 67 base::win::ScopedHandle job; |
69 scoped_refptr<sandbox::PolicyBase> policy; | 68 sandbox::PolicyBase* policy; |
70 }; | 69 }; |
71 | 70 |
72 void JobTracker::FreeResources() { | 71 void JobTracker::FreeResources() { |
73 if (policy) { | 72 if (policy) { |
74 BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK); | 73 BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK); |
75 DCHECK(res); | 74 DCHECK(res); |
76 // Closing the job causes the target process to be destroyed so this needs | 75 // Closing the job causes the target process to be destroyed so this needs |
77 // to happen before calling OnJobEmpty(). | 76 // to happen before calling OnJobEmpty(). |
78 HANDLE stale_job_handle = job.Get(); | 77 HANDLE stale_job_handle = job.Get(); |
79 job.Close(); | 78 job.Close(); |
80 | 79 |
81 // In OnJobEmpty() we don't actually use the job handle directly. | 80 // In OnJobEmpty() we don't actually use the job handle directly. |
82 policy->OnJobEmpty(stale_job_handle); | 81 policy->OnJobEmpty(stale_job_handle); |
83 policy = nullptr; | 82 policy->Release(); |
| 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 scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() { | 145 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 scoped_refptr<TargetPolicy> policy(new PolicyBase); | 148 return new PolicyBase; |
149 // PolicyBase starts with refcount 1. | |
150 policy->Release(); | |
151 return policy; | |
152 } | 149 } |
153 | 150 |
154 // The worker thread stays in a loop waiting for asynchronous notifications | 151 // The worker thread stays in a loop waiting for asynchronous notifications |
155 // 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 |
156 // 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 |
157 // the policy about events. | 154 // the policy about events. |
158 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { | 155 DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { |
159 if (NULL == param) | 156 if (NULL == param) |
160 return 1; | 157 return 1; |
161 | 158 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 } | 261 } |
265 | 262 |
266 NOTREACHED(); | 263 NOTREACHED(); |
267 return 0; | 264 return 0; |
268 } | 265 } |
269 | 266 |
270 // SpawnTarget does all the interesting sandbox setup and creates the target | 267 // SpawnTarget does all the interesting sandbox setup and creates the target |
271 // process inside the sandbox. | 268 // process inside the sandbox. |
272 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, | 269 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, |
273 const wchar_t* command_line, | 270 const wchar_t* command_line, |
274 scoped_refptr<TargetPolicy> policy, | 271 TargetPolicy* policy, |
275 ResultCode* last_warning, | 272 ResultCode* last_warning, |
276 DWORD* last_error, | 273 DWORD* last_error, |
277 PROCESS_INFORMATION* target_info) { | 274 PROCESS_INFORMATION* target_info) { |
278 if (!exe_path) | 275 if (!exe_path) |
279 return SBOX_ERROR_BAD_PARAMS; | 276 return SBOX_ERROR_BAD_PARAMS; |
280 | 277 |
281 if (!policy) | 278 if (!policy) |
282 return SBOX_ERROR_BAD_PARAMS; | 279 return SBOX_ERROR_BAD_PARAMS; |
283 | 280 |
284 // Even though the resources touched by SpawnTarget can be accessed in | 281 // Even though the resources touched by SpawnTarget can be accessed in |
285 // multiple threads, the method itself cannot be called from more than | 282 // multiple threads, the method itself cannot be called from more than |
286 // 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 |
287 // the child process. | 284 // the child process. |
288 static DWORD thread_id = ::GetCurrentThreadId(); | 285 static DWORD thread_id = ::GetCurrentThreadId(); |
289 DCHECK(thread_id == ::GetCurrentThreadId()); | 286 DCHECK(thread_id == ::GetCurrentThreadId()); |
290 *last_warning = SBOX_ALL_OK; | 287 *last_warning = SBOX_ALL_OK; |
291 | 288 |
292 AutoLock lock(&lock_); | 289 AutoLock lock(&lock_); |
293 | 290 |
294 // This downcast is safe as long as we control CreatePolicy() | 291 // This downcast is safe as long as we control CreatePolicy() |
295 scoped_refptr<PolicyBase> policy_base(static_cast<PolicyBase*>(policy.get())); | 292 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); |
296 | 293 |
297 // 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 |
298 // with the soon to be created target process. | 295 // with the soon to be created target process. |
299 base::win::ScopedHandle initial_token; | 296 base::win::ScopedHandle initial_token; |
300 base::win::ScopedHandle lockdown_token; | 297 base::win::ScopedHandle lockdown_token; |
301 base::win::ScopedHandle lowbox_token; | 298 base::win::ScopedHandle lowbox_token; |
302 ResultCode result = SBOX_ALL_OK; | 299 ResultCode result = SBOX_ALL_OK; |
303 | 300 |
304 result = | 301 result = |
305 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 Loading... |
437 result = policy_base->AddTarget(target); | 434 result = policy_base->AddTarget(target); |
438 | 435 |
439 if (result != SBOX_ALL_OK) { | 436 if (result != SBOX_ALL_OK) { |
440 *last_error = ::GetLastError(); | 437 *last_error = ::GetLastError(); |
441 SpawnCleanup(target); | 438 SpawnCleanup(target); |
442 return result; | 439 return result; |
443 } | 440 } |
444 | 441 |
445 // 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 |
446 // the job object generates notifications using the completion port. | 443 // the job object generates notifications using the completion port. |
| 444 policy_base->AddRef(); |
447 if (job.IsValid()) { | 445 if (job.IsValid()) { |
448 std::unique_ptr<JobTracker> tracker( | 446 std::unique_ptr<JobTracker> tracker( |
449 new JobTracker(std::move(job), policy_base)); | 447 new JobTracker(std::move(job), policy_base)); |
450 | 448 |
451 // There is no obvious recovery after failure here. Previous version with | 449 // There is no obvious recovery after failure here. Previous version with |
452 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639 | 450 // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639 |
453 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), | 451 CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), |
454 tracker.get())); | 452 tracker.get())); |
455 | 453 |
456 // Save the tracker because in cleanup we might need to force closing | 454 // Save the tracker because in cleanup we might need to force closing |
(...skipping 17 matching lines...) Expand all Loading... |
474 ::WaitForSingleObject(no_targets_.Get(), INFINITE); | 472 ::WaitForSingleObject(no_targets_.Get(), INFINITE); |
475 return SBOX_ALL_OK; | 473 return SBOX_ALL_OK; |
476 } | 474 } |
477 | 475 |
478 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { | 476 bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { |
479 AutoLock lock(&lock_); | 477 AutoLock lock(&lock_); |
480 return child_process_ids_.find(process_id) != child_process_ids_.end(); | 478 return child_process_ids_.find(process_id) != child_process_ids_.end(); |
481 } | 479 } |
482 | 480 |
483 } // namespace sandbox | 481 } // namespace sandbox |
OLD | NEW |