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

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

Issue 9959018: Use ScopedProcessInformation and other RAII types in sandbox. (Closed) Base URL: svn://svn.chromium.org/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
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 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/threading/platform_thread.h" 9 #include "base/threading/platform_thread.h"
10 #include "base/win/scoped_handle.h"
11 #include "base/win/scoped_process_information.h"
9 #include "sandbox/src/sandbox_policy_base.h" 12 #include "sandbox/src/sandbox_policy_base.h"
10 #include "sandbox/src/sandbox.h" 13 #include "sandbox/src/sandbox.h"
11 #include "sandbox/src/target_process.h" 14 #include "sandbox/src/target_process.h"
12 #include "sandbox/src/win2k_threadpool.h" 15 #include "sandbox/src/win2k_threadpool.h"
13 #include "sandbox/src/win_utils.h" 16 #include "sandbox/src/win_utils.h"
14 17
15 namespace { 18 namespace {
16 19
17 // Utility function to associate a completion port to a job object. 20 // Utility function to associate a completion port to a job object.
18 bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) { 21 bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 NOTREACHED(); 213 NOTREACHED();
211 } 214 }
212 } 215 }
213 216
214 NOTREACHED(); 217 NOTREACHED();
215 return 0; 218 return 0;
216 } 219 }
217 220
218 // SpawnTarget does all the interesting sandbox setup and creates the target 221 // SpawnTarget does all the interesting sandbox setup and creates the target
219 // process inside the sandbox. 222 // process inside the sandbox.
220 ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, 223 ResultCode BrokerServicesBase::SpawnTarget(
221 const wchar_t* command_line, 224 const wchar_t* exe_path,
222 TargetPolicy* policy, 225 const wchar_t* command_line,
223 PROCESS_INFORMATION* target_info) { 226 TargetPolicy* policy,
227 base::win::ScopedProcessInformation* target_info) {
224 if (!exe_path) 228 if (!exe_path)
225 return SBOX_ERROR_BAD_PARAMS; 229 return SBOX_ERROR_BAD_PARAMS;
226 230
227 if (!policy) 231 if (!policy)
228 return SBOX_ERROR_BAD_PARAMS; 232 return SBOX_ERROR_BAD_PARAMS;
229 233
230 // Even though the resources touched by SpawnTarget can be accessed in 234 // Even though the resources touched by SpawnTarget can be accessed in
231 // multiple threads, the method itself cannot be called from more than 235 // multiple threads, the method itself cannot be called from more than
232 // 1 thread. This is to protect the global variables used while setting up 236 // 1 thread. This is to protect the global variables used while setting up
233 // the child process. 237 // the child process.
234 static DWORD thread_id = ::GetCurrentThreadId(); 238 static DWORD thread_id = ::GetCurrentThreadId();
235 DCHECK(thread_id == ::GetCurrentThreadId()); 239 DCHECK(thread_id == ::GetCurrentThreadId());
236 240
237 AutoLock lock(&lock_); 241 AutoLock lock(&lock_);
238 242
239 // This downcast is safe as long as we control CreatePolicy() 243 // This downcast is safe as long as we control CreatePolicy()
240 PolicyBase* policy_base = static_cast<PolicyBase*>(policy); 244 PolicyBase* policy_base = static_cast<PolicyBase*>(policy);
241 245
242 // Construct the tokens and the job object that we are going to associate 246 // Construct the tokens and the job object that we are going to associate
243 // with the soon to be created target process. 247 // with the soon to be created target process.
244 HANDLE lockdown_token = NULL; 248 base::win::ScopedHandle lockdown_token;
245 HANDLE initial_token = NULL; 249 base::win::ScopedHandle initial_token;
246 DWORD win_result = policy_base->MakeTokens(&initial_token, &lockdown_token); 250 DWORD win_result = policy_base->MakeTokens(initial_token.Receive(),
251 lockdown_token.Receive());
247 if (ERROR_SUCCESS != win_result) 252 if (ERROR_SUCCESS != win_result)
248 return SBOX_ERROR_GENERIC; 253 return SBOX_ERROR_GENERIC;
249 254
250 HANDLE job = NULL; 255 base::win::ScopedHandle job;
251 win_result = policy_base->MakeJobObject(&job); 256 win_result = policy_base->MakeJobObject(job.Receive());
252 if (ERROR_SUCCESS != win_result) 257 if (ERROR_SUCCESS != win_result)
erikwright (departed) 2012/03/30 16:29:31 Previously lockdown_token and initial_token could
253 return SBOX_ERROR_GENERIC; 258 return SBOX_ERROR_GENERIC;
254 259
255 if (ERROR_ALREADY_EXISTS == ::GetLastError()) 260 if (ERROR_ALREADY_EXISTS == ::GetLastError())
256 return SBOX_ERROR_GENERIC; 261 return SBOX_ERROR_GENERIC;
257 262
258 // Construct the thread pool here in case it is expensive. 263 // Construct the thread pool here in case it is expensive.
259 // The thread pool is shared by all the targets 264 // The thread pool is shared by all the targets
260 if (NULL == thread_pool_) 265 if (NULL == thread_pool_)
261 thread_pool_ = new Win2kThreadPool(); 266 thread_pool_ = new Win2kThreadPool();
262 267
263 // Create the TargetProces object and spawn the target suspended. Note that 268 // Create the TargetProces object and spawn the target suspended. Note that
264 // Brokerservices does not own the target object. It is owned by the Policy. 269 // Brokerservices does not own the target object. It is owned by the Policy.
265 PROCESS_INFORMATION process_info = {0}; 270 base::win::ScopedProcessInformation process_info;
266 TargetProcess* target = new TargetProcess(initial_token, lockdown_token, 271 TargetProcess* target = new TargetProcess(initial_token.Take(),
267 job, thread_pool_); 272 lockdown_token.Take(),
273 job,
274 thread_pool_);
268 275
269 std::wstring desktop = policy_base->GetAlternateDesktop(); 276 std::wstring desktop = policy_base->GetAlternateDesktop();
270 277
271 win_result = target->Create(exe_path, command_line, 278 win_result = target->Create(exe_path, command_line,
272 desktop.empty() ? NULL : desktop.c_str(), 279 desktop.empty() ? NULL : desktop.c_str(),
273 &process_info); 280 &process_info);
274 if (ERROR_SUCCESS != win_result) 281 if (ERROR_SUCCESS != win_result)
erikwright (departed) 2012/03/30 16:29:31 Previously job could be leaked here and in the fol
275 return SpawnCleanup(target, win_result); 282 return SpawnCleanup(target, win_result);
276 283
277 if ((INVALID_HANDLE_VALUE == process_info.hProcess) ||
erikwright (departed) 2012/03/30 16:29:31 This check was redundant. It only protects you if
278 (INVALID_HANDLE_VALUE == process_info.hThread))
279 return SpawnCleanup(target, win_result);
280
281 // Now the policy is the owner of the target. 284 // Now the policy is the owner of the target.
282 if (!policy_base->AddTarget(target)) { 285 if (!policy_base->AddTarget(target)) {
283 return SpawnCleanup(target, 0); 286 return SpawnCleanup(target, 0);
284 } 287 }
285 288
286 // We are going to keep a pointer to the policy because we'll call it when 289 // We are going to keep a pointer to the policy because we'll call it when
287 // the job object generates notifications using the completion port. 290 // the job object generates notifications using the completion port.
288 policy_base->AddRef(); 291 policy_base->AddRef();
289 JobTracker* tracker = new JobTracker(job, policy_base); 292 scoped_ptr<JobTracker> tracker(new JobTracker(job.Take(), policy_base));
290 if (!AssociateCompletionPort(job, job_port_, tracker)) 293 if (!AssociateCompletionPort(tracker->job, job_port_, tracker.get()))
291 return SpawnCleanup(target, 0); 294 return SpawnCleanup(target, 0);
erikwright (departed) 2012/03/30 16:29:31 tracker was previously leaked here.
292 // Save the tracker because in cleanup we might need to force closing 295 // Save the tracker because in cleanup we might need to force closing
293 // the Jobs. 296 // the Jobs.
294 tracker_list_.push_back(tracker); 297 tracker_list_.push_back(tracker.release());
295 298
296 // We return the caller a duplicate of the process handle so they 299 target_info->Swap(&process_info);
297 // can close it at will.
298 HANDLE dup_process_handle = NULL;
299 if (!::DuplicateHandle(::GetCurrentProcess(), process_info.hProcess,
300 ::GetCurrentProcess(), &dup_process_handle,
301 0, FALSE, DUPLICATE_SAME_ACCESS))
erikwright (departed) 2012/03/30 16:29:31 The responsibility for duplicating is now in Targe
302 return SpawnCleanup(target, 0);
303 300
304 *target_info = process_info;
305 target_info->hProcess = dup_process_handle;
306 return SBOX_ALL_OK; 301 return SBOX_ALL_OK;
307 } 302 }
308 303
309 304
310 ResultCode BrokerServicesBase::WaitForAllTargets() { 305 ResultCode BrokerServicesBase::WaitForAllTargets() {
311 ::WaitForSingleObject(no_targets_, INFINITE); 306 ::WaitForSingleObject(no_targets_, INFINITE);
312 return SBOX_ALL_OK; 307 return SBOX_ALL_OK;
313 } 308 }
314 309
315 } // namespace sandbox 310 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698