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 "content/common/sandbox_win.h" | 5 #include "content/common/sandbox_win.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 NOTREACHED() << "QueryInformationJobObject failed. " << GetLastError(); | 274 NOTREACHED() << "QueryInformationJobObject failed. " << GetLastError(); |
275 return true; | 275 return true; |
276 } | 276 } |
277 if (job_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) | 277 if (job_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) |
278 return true; | 278 return true; |
279 | 279 |
280 return false; | 280 return false; |
281 } | 281 } |
282 | 282 |
283 // Adds the generic policy rules to a sandbox TargetPolicy. | 283 // Adds the generic policy rules to a sandbox TargetPolicy. |
284 bool AddGenericPolicy(sandbox::TargetPolicy* policy) { | 284 sandbox::ResultCode AddGenericPolicy(sandbox::TargetPolicy* policy) { |
285 sandbox::ResultCode result; | 285 sandbox::ResultCode result; |
286 | 286 |
287 // Add the policy for the client side of a pipe. It is just a file | 287 // Add the policy for the client side of a pipe. It is just a file |
288 // in the \pipe\ namespace. We restrict it to pipes that start with | 288 // in the \pipe\ namespace. We restrict it to pipes that start with |
289 // "chrome." so the sandboxed process cannot connect to system services. | 289 // "chrome." so the sandboxed process cannot connect to system services. |
290 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 290 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
291 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 291 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
292 L"\\??\\pipe\\chrome.*"); | 292 L"\\??\\pipe\\chrome.*"); |
293 if (result != sandbox::SBOX_ALL_OK) | 293 if (result != sandbox::SBOX_ALL_OK) |
294 return false; | 294 return result; |
295 | 295 |
296 // Add the policy for the server side of nacl pipe. It is just a file | 296 // Add the policy for the server side of nacl pipe. It is just a file |
297 // in the \pipe\ namespace. We restrict it to pipes that start with | 297 // in the \pipe\ namespace. We restrict it to pipes that start with |
298 // "chrome.nacl" so the sandboxed process cannot connect to | 298 // "chrome.nacl" so the sandboxed process cannot connect to |
299 // system services. | 299 // system services. |
300 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | 300 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, |
301 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | 301 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, |
302 L"\\\\.\\pipe\\chrome.nacl.*"); | 302 L"\\\\.\\pipe\\chrome.nacl.*"); |
303 if (result != sandbox::SBOX_ALL_OK) | 303 if (result != sandbox::SBOX_ALL_OK) |
304 return false; | 304 return result; |
305 | 305 |
306 // Allow the server side of sync sockets, which are pipes that have | 306 // Allow the server side of sync sockets, which are pipes that have |
307 // the "chrome.sync" namespace and a randomly generated suffix. | 307 // the "chrome.sync" namespace and a randomly generated suffix. |
308 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | 308 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, |
309 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | 309 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, |
310 L"\\\\.\\pipe\\chrome.sync.*"); | 310 L"\\\\.\\pipe\\chrome.sync.*"); |
311 if (result != sandbox::SBOX_ALL_OK) | 311 if (result != sandbox::SBOX_ALL_OK) |
312 return false; | 312 return result; |
313 | 313 |
314 // Add the policy for debug message only in debug | 314 // Add the policy for debug message only in debug |
315 #ifndef NDEBUG | 315 #ifndef NDEBUG |
316 base::FilePath app_dir; | 316 base::FilePath app_dir; |
317 if (!PathService::Get(base::DIR_MODULE, &app_dir)) | 317 if (!PathService::Get(base::DIR_MODULE, &app_dir)) |
318 return false; | 318 return false; |
319 | 319 |
320 wchar_t long_path_buf[MAX_PATH]; | 320 wchar_t long_path_buf[MAX_PATH]; |
321 DWORD long_path_return_value = GetLongPathName(app_dir.value().c_str(), | 321 DWORD long_path_return_value = GetLongPathName(app_dir.value().c_str(), |
322 long_path_buf, | 322 long_path_buf, |
323 MAX_PATH); | 323 MAX_PATH); |
324 if (long_path_return_value == 0 || long_path_return_value >= MAX_PATH) | 324 if (long_path_return_value == 0 || long_path_return_value >= MAX_PATH) |
325 return false; | 325 return false; |
326 | 326 |
327 base::FilePath debug_message(long_path_buf); | 327 base::FilePath debug_message(long_path_buf); |
328 debug_message = debug_message.AppendASCII("debug_message.exe"); | 328 debug_message = debug_message.AppendASCII("debug_message.exe"); |
329 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS, | 329 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS, |
330 sandbox::TargetPolicy::PROCESS_MIN_EXEC, | 330 sandbox::TargetPolicy::PROCESS_MIN_EXEC, |
331 debug_message.value().c_str()); | 331 debug_message.value().c_str()); |
332 if (result != sandbox::SBOX_ALL_OK) | 332 if (result != sandbox::SBOX_ALL_OK) |
333 return false; | 333 return result; |
334 #endif // NDEBUG | 334 #endif // NDEBUG |
335 | 335 |
336 // Add the policy for read-only PDB file access for stack traces. | 336 // Add the policy for read-only PDB file access for stack traces. |
337 #if !defined(OFFICIAL_BUILD) | 337 #if !defined(OFFICIAL_BUILD) |
338 base::FilePath exe; | 338 base::FilePath exe; |
339 if (!PathService::Get(base::FILE_EXE, &exe)) | 339 if (!PathService::Get(base::FILE_EXE, &exe)) |
340 return false; | 340 return sandbox::SBOX_ERROR_GENERIC; |
341 base::FilePath pdb_path = exe.DirName().Append(L"*.pdb"); | 341 base::FilePath pdb_path = exe.DirName().Append(L"*.pdb"); |
342 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 342 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
343 sandbox::TargetPolicy::FILES_ALLOW_READONLY, | 343 sandbox::TargetPolicy::FILES_ALLOW_READONLY, |
344 pdb_path.value().c_str()); | 344 pdb_path.value().c_str()); |
345 if (result != sandbox::SBOX_ALL_OK) | 345 if (result != sandbox::SBOX_ALL_OK) |
346 return false; | 346 return result; |
347 #endif | 347 #endif |
348 | 348 |
349 #if defined(SANITIZER_COVERAGE) | 349 #if defined(SANITIZER_COVERAGE) |
350 DWORD coverage_dir_size = | 350 DWORD coverage_dir_size = |
351 ::GetEnvironmentVariable(L"SANITIZER_COVERAGE_DIR", NULL, 0); | 351 ::GetEnvironmentVariable(L"SANITIZER_COVERAGE_DIR", NULL, 0); |
352 if (coverage_dir_size == 0) { | 352 if (coverage_dir_size == 0) { |
353 LOG(WARNING) << "SANITIZER_COVERAGE_DIR was not set, coverage won't work."; | 353 LOG(WARNING) << "SANITIZER_COVERAGE_DIR was not set, coverage won't work."; |
354 } else { | 354 } else { |
355 std::wstring coverage_dir; | 355 std::wstring coverage_dir; |
356 wchar_t* coverage_dir_str = | 356 wchar_t* coverage_dir_str = |
357 base::WriteInto(&coverage_dir, coverage_dir_size); | 357 base::WriteInto(&coverage_dir, coverage_dir_size); |
358 coverage_dir_size = ::GetEnvironmentVariable( | 358 coverage_dir_size = ::GetEnvironmentVariable( |
359 L"SANITIZER_COVERAGE_DIR", coverage_dir_str, coverage_dir_size); | 359 L"SANITIZER_COVERAGE_DIR", coverage_dir_str, coverage_dir_size); |
360 CHECK(coverage_dir.size() == coverage_dir_size); | 360 CHECK(coverage_dir.size() == coverage_dir_size); |
361 base::FilePath sancov_path = | 361 base::FilePath sancov_path = |
362 base::FilePath(coverage_dir).Append(L"*.sancov"); | 362 base::FilePath(coverage_dir).Append(L"*.sancov"); |
363 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 363 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
364 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 364 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
365 sancov_path.value().c_str()); | 365 sancov_path.value().c_str()); |
366 if (result != sandbox::SBOX_ALL_OK) | 366 if (result != sandbox::SBOX_ALL_OK) |
367 return false; | 367 return result; |
368 } | 368 } |
369 #endif | 369 #endif |
370 | 370 |
371 AddGenericDllEvictionPolicy(policy); | 371 AddGenericDllEvictionPolicy(policy); |
372 return true; | 372 return sandbox::SBOX_ALL_OK; |
373 } | 373 } |
374 | 374 |
375 bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) { | 375 sandbox::ResultCode AddPolicyForSandboxedProcess( |
| 376 sandbox::TargetPolicy* policy) { |
376 sandbox::ResultCode result = sandbox::SBOX_ALL_OK; | 377 sandbox::ResultCode result = sandbox::SBOX_ALL_OK; |
377 | 378 |
378 // Win8+ adds a device DeviceApi that we don't need. | 379 // Win8+ adds a device DeviceApi that we don't need. |
379 if (base::win::GetVersion() > base::win::VERSION_WIN7) | 380 if (base::win::GetVersion() > base::win::VERSION_WIN7) |
380 result = policy->AddKernelObjectToClose(L"File", L"\\Device\\DeviceApi"); | 381 result = policy->AddKernelObjectToClose(L"File", L"\\Device\\DeviceApi"); |
381 if (result != sandbox::SBOX_ALL_OK) | 382 if (result != sandbox::SBOX_ALL_OK) |
382 return false; | 383 return result; |
383 | 384 |
384 // Close the proxy settings on XP. | 385 // Close the proxy settings on XP. |
385 if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003) | 386 if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003) |
386 result = policy->AddKernelObjectToClose(L"Key", | 387 result = policy->AddKernelObjectToClose(L"Key", |
387 L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\" \ | 388 L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\" \ |
388 L"CurrentVersion\\Internet Settings"); | 389 L"CurrentVersion\\Internet Settings"); |
389 if (result != sandbox::SBOX_ALL_OK) | 390 if (result != sandbox::SBOX_ALL_OK) |
390 return false; | 391 return result; |
391 | 392 |
392 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; | 393 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; |
393 if (base::win::GetVersion() > base::win::VERSION_XP) { | 394 if (base::win::GetVersion() > base::win::VERSION_XP) { |
394 // On 2003/Vista the initial token has to be restricted if the main | 395 // On 2003/Vista the initial token has to be restricted if the main |
395 // token is restricted. | 396 // token is restricted. |
396 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; | 397 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; |
397 } | 398 } |
398 | 399 |
399 policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); | 400 result = policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); |
| 401 if (result != sandbox::SBOX_ALL_OK) |
| 402 return result; |
400 // Prevents the renderers from manipulating low-integrity processes. | 403 // Prevents the renderers from manipulating low-integrity processes. |
401 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED); | 404 result = policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED); |
402 policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | 405 if (result != sandbox::SBOX_ALL_OK) |
| 406 return result; |
| 407 result = policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); |
| 408 if (result != sandbox::SBOX_ALL_OK) |
| 409 return result; |
403 policy->SetLockdownDefaultDacl(); | 410 policy->SetLockdownDefaultDacl(); |
404 | 411 |
405 if (sandbox::SBOX_ALL_OK != policy->SetAlternateDesktop(true)) { | 412 result = policy->SetAlternateDesktop(true); |
| 413 if (result != sandbox::SBOX_ALL_OK) { |
406 DLOG(WARNING) << "Failed to apply desktop security to the renderer"; | 414 DLOG(WARNING) << "Failed to apply desktop security to the renderer"; |
| 415 return result; |
407 } | 416 } |
408 | 417 |
409 return true; | 418 return result; |
410 } | 419 } |
411 | 420 |
412 // Updates the command line arguments with debug-related flags. If debug flags | 421 // Updates the command line arguments with debug-related flags. If debug flags |
413 // have been used with this process, they will be filtered and added to | 422 // have been used with this process, they will be filtered and added to |
414 // command_line as needed. | 423 // command_line as needed. |
415 void ProcessDebugFlags(base::CommandLine* command_line) { | 424 void ProcessDebugFlags(base::CommandLine* command_line) { |
416 const base::CommandLine& current_cmd_line = | 425 const base::CommandLine& current_cmd_line = |
417 *base::CommandLine::ForCurrentProcess(); | 426 *base::CommandLine::ForCurrentProcess(); |
418 std::string type = command_line->GetSwitchValueASCII(switches::kProcessType); | 427 std::string type = command_line->GetSwitchValueASCII(switches::kProcessType); |
419 if (current_cmd_line.HasSwitch(switches::kWaitForDebuggerChildren)) { | 428 if (current_cmd_line.HasSwitch(switches::kWaitForDebuggerChildren)) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 if (command_line.HasSwitch(switches::kDisableAppContainer)) | 550 if (command_line.HasSwitch(switches::kDisableAppContainer)) |
542 return false; | 551 return false; |
543 if (command_line.HasSwitch(switches::kEnableAppContainer)) | 552 if (command_line.HasSwitch(switches::kEnableAppContainer)) |
544 return true; | 553 return true; |
545 return base::StartsWith(appcontainer_group_name, "Enabled", | 554 return base::StartsWith(appcontainer_group_name, "Enabled", |
546 base::CompareCase::INSENSITIVE_ASCII); | 555 base::CompareCase::INSENSITIVE_ASCII); |
547 } | 556 } |
548 | 557 |
549 } // namespace | 558 } // namespace |
550 | 559 |
551 void SetJobLevel(const base::CommandLine& cmd_line, | 560 sandbox::ResultCode SetJobLevel(const base::CommandLine& cmd_line, |
552 sandbox::JobLevel job_level, | 561 sandbox::JobLevel job_level, |
553 uint32_t ui_exceptions, | 562 uint32_t ui_exceptions, |
554 sandbox::TargetPolicy* policy) { | 563 sandbox::TargetPolicy* policy) { |
555 if (ShouldSetJobLevel(cmd_line)) { | 564 if (!ShouldSetJobLevel(cmd_line)) |
| 565 return policy->SetJobLevel(sandbox::JOB_NONE, 0); |
| 566 |
556 #ifdef _WIN64 | 567 #ifdef _WIN64 |
557 policy->SetJobMemoryLimit(4ULL * 1024 * 1024 * 1024); | 568 sandbox::ResultCode ret = |
| 569 policy->SetJobMemoryLimit(4ULL * 1024 * 1024 * 1024); |
| 570 if (ret != sandbox::SBOX_ALL_OK) |
| 571 return ret; |
558 #endif | 572 #endif |
559 policy->SetJobLevel(job_level, ui_exceptions); | 573 return policy->SetJobLevel(job_level, ui_exceptions); |
560 } else { | |
561 policy->SetJobLevel(sandbox::JOB_NONE, 0); | |
562 } | |
563 } | 574 } |
564 | 575 |
565 // TODO(jschuh): Need get these restrictions applied to NaCl and Pepper. | 576 // TODO(jschuh): Need get these restrictions applied to NaCl and Pepper. |
566 // Just have to figure out what needs to be warmed up first. | 577 // Just have to figure out what needs to be warmed up first. |
567 void AddBaseHandleClosePolicy(sandbox::TargetPolicy* policy) { | 578 sandbox::ResultCode AddBaseHandleClosePolicy(sandbox::TargetPolicy* policy) { |
568 // TODO(cpu): Add back the BaseNamedObjects policy. | 579 // TODO(cpu): Add back the BaseNamedObjects policy. |
569 base::string16 object_path = PrependWindowsSessionPath( | 580 base::string16 object_path = PrependWindowsSessionPath( |
570 L"\\BaseNamedObjects\\windows_shell_global_counters"); | 581 L"\\BaseNamedObjects\\windows_shell_global_counters"); |
571 policy->AddKernelObjectToClose(L"Section", object_path.data()); | 582 return policy->AddKernelObjectToClose(L"Section", object_path.data()); |
572 } | 583 } |
573 | 584 |
574 void AddAppContainerPolicy(sandbox::TargetPolicy* policy, const wchar_t* sid) { | 585 sandbox::ResultCode AddAppContainerPolicy(sandbox::TargetPolicy* policy, |
| 586 const wchar_t* sid) { |
575 if (IsAppContainerEnabled()) | 587 if (IsAppContainerEnabled()) |
576 policy->SetLowBox(sid); | 588 return policy->SetLowBox(sid); |
| 589 return sandbox::SBOX_ALL_OK; |
577 } | 590 } |
578 | 591 |
579 bool AddWin32kLockdownPolicy(sandbox::TargetPolicy* policy, bool enable_opm) { | 592 sandbox::ResultCode AddWin32kLockdownPolicy(sandbox::TargetPolicy* policy, |
| 593 bool enable_opm) { |
580 #if !defined(NACL_WIN64) | 594 #if !defined(NACL_WIN64) |
581 if (!IsWin32kRendererLockdownEnabled()) | 595 if (!IsWin32kRendererLockdownEnabled()) |
582 return true; | 596 return sandbox::SBOX_ALL_OK; |
583 | 597 |
584 // Enable win32k lockdown if not already. | 598 // Enable win32k lockdown if not already. |
585 sandbox::MitigationFlags flags = policy->GetProcessMitigations(); | 599 sandbox::MitigationFlags flags = policy->GetProcessMitigations(); |
586 if ((flags & sandbox::MITIGATION_WIN32K_DISABLE) == | 600 if ((flags & sandbox::MITIGATION_WIN32K_DISABLE) == |
587 sandbox::MITIGATION_WIN32K_DISABLE) | 601 sandbox::MITIGATION_WIN32K_DISABLE) |
588 return true; | 602 return sandbox::SBOX_ALL_OK; |
589 | 603 |
590 sandbox::ResultCode result = | 604 sandbox::ResultCode result = |
591 policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, | 605 policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, |
592 enable_opm ? sandbox::TargetPolicy::IMPLEMENT_OPM_APIS | 606 enable_opm ? sandbox::TargetPolicy::IMPLEMENT_OPM_APIS |
593 : sandbox::TargetPolicy::FAKE_USER_GDI_INIT, | 607 : sandbox::TargetPolicy::FAKE_USER_GDI_INIT, |
594 nullptr); | 608 nullptr); |
595 if (result != sandbox::SBOX_ALL_OK) | 609 if (result != sandbox::SBOX_ALL_OK) |
596 return false; | 610 return result; |
597 if (enable_opm) | 611 if (enable_opm) |
598 policy->SetEnableOPMRedirection(); | 612 policy->SetEnableOPMRedirection(); |
| 613 |
599 flags |= sandbox::MITIGATION_WIN32K_DISABLE; | 614 flags |= sandbox::MITIGATION_WIN32K_DISABLE; |
600 result = policy->SetProcessMitigations(flags); | 615 return policy->SetProcessMitigations(flags); |
601 if (result != sandbox::SBOX_ALL_OK) | 616 #else |
602 return false; | 617 return sandbox::SBOX_ALL_OK; |
603 #endif | 618 #endif |
604 return true; | |
605 } | 619 } |
606 | 620 |
607 bool InitBrokerServices(sandbox::BrokerServices* broker_services) { | 621 bool InitBrokerServices(sandbox::BrokerServices* broker_services) { |
608 // TODO(abarth): DCHECK(CalledOnValidThread()); | 622 // TODO(abarth): DCHECK(CalledOnValidThread()); |
609 // See <http://b/1287166>. | 623 // See <http://b/1287166>. |
610 DCHECK(broker_services); | 624 DCHECK(broker_services); |
611 DCHECK(!g_broker_services); | 625 DCHECK(!g_broker_services); |
612 sandbox::ResultCode result = broker_services->Init(); | 626 sandbox::ResultCode result = broker_services->Init(); |
613 g_broker_services = broker_services; | 627 g_broker_services = broker_services; |
614 | 628 |
(...skipping 29 matching lines...) Expand all Loading... |
644 } | 658 } |
645 | 659 |
646 bool InitTargetServices(sandbox::TargetServices* target_services) { | 660 bool InitTargetServices(sandbox::TargetServices* target_services) { |
647 DCHECK(target_services); | 661 DCHECK(target_services); |
648 DCHECK(!g_target_services); | 662 DCHECK(!g_target_services); |
649 sandbox::ResultCode result = target_services->Init(); | 663 sandbox::ResultCode result = target_services->Init(); |
650 g_target_services = target_services; | 664 g_target_services = target_services; |
651 return sandbox::SBOX_ALL_OK == result; | 665 return sandbox::SBOX_ALL_OK == result; |
652 } | 666 } |
653 | 667 |
654 base::Process StartSandboxedProcess( | 668 sandbox::ResultCode StartSandboxedProcess( |
655 SandboxedProcessLauncherDelegate* delegate, | 669 SandboxedProcessLauncherDelegate* delegate, |
656 base::CommandLine* cmd_line, | 670 base::CommandLine* cmd_line, |
657 const base::HandlesToInheritVector& handles_to_inherit) { | 671 const base::HandlesToInheritVector& handles_to_inherit, |
| 672 base::Process* process) { |
658 DCHECK(delegate); | 673 DCHECK(delegate); |
659 const base::CommandLine& browser_command_line = | 674 const base::CommandLine& browser_command_line = |
660 *base::CommandLine::ForCurrentProcess(); | 675 *base::CommandLine::ForCurrentProcess(); |
661 std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType); | 676 std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType); |
662 | 677 |
663 TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); | 678 TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); |
664 | 679 |
665 // Propagate the --allow-no-job flag if present. | 680 // Propagate the --allow-no-job flag if present. |
666 if (browser_command_line.HasSwitch(switches::kAllowNoSandboxJob) && | 681 if (browser_command_line.HasSwitch(switches::kAllowNoSandboxJob) && |
667 !cmd_line->HasSwitch(switches::kAllowNoSandboxJob)) { | 682 !cmd_line->HasSwitch(switches::kAllowNoSandboxJob)) { |
668 cmd_line->AppendSwitch(switches::kAllowNoSandboxJob); | 683 cmd_line->AppendSwitch(switches::kAllowNoSandboxJob); |
669 } | 684 } |
670 | 685 |
671 ProcessDebugFlags(cmd_line); | 686 ProcessDebugFlags(cmd_line); |
672 | 687 |
673 if ((!delegate->ShouldSandbox()) || | 688 if ((!delegate->ShouldSandbox()) || |
674 browser_command_line.HasSwitch(switches::kNoSandbox) || | 689 browser_command_line.HasSwitch(switches::kNoSandbox) || |
675 cmd_line->HasSwitch(switches::kNoSandbox)) { | 690 cmd_line->HasSwitch(switches::kNoSandbox)) { |
676 base::LaunchOptions options; | 691 base::LaunchOptions options; |
677 | 692 |
678 base::HandlesToInheritVector handles = handles_to_inherit; | 693 base::HandlesToInheritVector handles = handles_to_inherit; |
679 if (!handles_to_inherit.empty()) { | 694 if (!handles_to_inherit.empty()) { |
680 options.inherit_handles = true; | 695 options.inherit_handles = true; |
681 options.handles_to_inherit = &handles; | 696 options.handles_to_inherit = &handles; |
682 } | 697 } |
683 base::Process process = base::LaunchProcess(*cmd_line, options); | 698 base::Process unsandboxed_process = base::LaunchProcess(*cmd_line, options); |
684 | 699 |
685 // TODO(rvargas) crbug.com/417532: Don't share a raw handle. | 700 // TODO(rvargas) crbug.com/417532: Don't share a raw handle. |
686 g_broker_services->AddTargetPeer(process.Handle()); | 701 g_broker_services->AddTargetPeer(unsandboxed_process.Handle()); |
687 return process; | 702 |
| 703 *process = std::move(unsandboxed_process); |
| 704 return sandbox::SBOX_ALL_OK; |
688 } | 705 } |
689 | 706 |
690 sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy(); | 707 sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy(); |
691 | 708 |
692 // Add any handles to be inherited to the policy. | 709 // Add any handles to be inherited to the policy. |
693 for (HANDLE handle : handles_to_inherit) | 710 for (HANDLE handle : handles_to_inherit) |
694 policy->AddHandleToShare(handle); | 711 policy->AddHandleToShare(handle); |
695 | 712 |
696 // Pre-startup mitigations. | 713 // Pre-startup mitigations. |
697 sandbox::MitigationFlags mitigations = | 714 sandbox::MitigationFlags mitigations = |
698 sandbox::MITIGATION_HEAP_TERMINATE | | 715 sandbox::MITIGATION_HEAP_TERMINATE | |
699 sandbox::MITIGATION_BOTTOM_UP_ASLR | | 716 sandbox::MITIGATION_BOTTOM_UP_ASLR | |
700 sandbox::MITIGATION_DEP | | 717 sandbox::MITIGATION_DEP | |
701 sandbox::MITIGATION_DEP_NO_ATL_THUNK | | 718 sandbox::MITIGATION_DEP_NO_ATL_THUNK | |
702 sandbox::MITIGATION_SEHOP | | 719 sandbox::MITIGATION_SEHOP | |
703 sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE | | 720 sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE | |
704 sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | | 721 sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | |
705 sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; | 722 sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; |
706 #if !defined(NACL_WIN64) | 723 #if !defined(NACL_WIN64) |
707 // Don't block font loading with GDI. | 724 // Don't block font loading with GDI. |
708 if (!gfx::win::ShouldUseDirectWrite()) | 725 if (!gfx::win::ShouldUseDirectWrite()) |
709 mitigations ^= sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE; | 726 mitigations ^= sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE; |
710 #endif | 727 #endif |
711 | 728 |
712 if (policy->SetProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK) | 729 sandbox::ResultCode result = sandbox::SBOX_ERROR_GENERIC; |
713 return base::Process(); | 730 |
| 731 result = policy->SetProcessMitigations(mitigations); |
| 732 |
| 733 if (result != sandbox::SBOX_ALL_OK) |
| 734 return result; |
714 | 735 |
715 #if !defined(NACL_WIN64) | 736 #if !defined(NACL_WIN64) |
716 if (type_str == switches::kRendererProcess && | 737 if (type_str == switches::kRendererProcess && |
717 IsWin32kRendererLockdownEnabled()) { | 738 IsWin32kRendererLockdownEnabled()) { |
718 if (!AddWin32kLockdownPolicy(policy, false)) | 739 result = AddWin32kLockdownPolicy(policy, false); |
719 return base::Process(); | 740 if (result != sandbox::SBOX_ALL_OK) |
| 741 return result; |
720 } | 742 } |
721 #endif | 743 #endif |
722 | 744 |
723 // Post-startup mitigations. | 745 // Post-startup mitigations. |
724 mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS | | 746 mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS | |
725 sandbox::MITIGATION_DLL_SEARCH_ORDER; | 747 sandbox::MITIGATION_DLL_SEARCH_ORDER; |
726 | 748 |
727 if (policy->SetDelayedProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK) | 749 result = policy->SetDelayedProcessMitigations(mitigations); |
728 return base::Process(); | 750 if (result != sandbox::SBOX_ALL_OK) |
| 751 return result; |
729 | 752 |
730 SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy); | 753 result = SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy); |
| 754 if (result != sandbox::SBOX_ALL_OK) |
| 755 return result; |
731 | 756 |
732 if (!delegate->DisableDefaultPolicy()) { | 757 if (!delegate->DisableDefaultPolicy()) { |
733 if (!AddPolicyForSandboxedProcess(policy)) | 758 result = AddPolicyForSandboxedProcess(policy); |
734 return base::Process(); | 759 if (result != sandbox::SBOX_ALL_OK) |
| 760 return result; |
735 } | 761 } |
736 | 762 |
737 #if !defined(NACL_WIN64) | 763 #if !defined(NACL_WIN64) |
738 // NOTE: This is placed at function scope so that it stays alive through | 764 // NOTE: This is placed at function scope so that it stays alive through |
739 // process launch. | 765 // process launch. |
740 base::SharedMemory direct_write_font_cache_section; | 766 base::SharedMemory direct_write_font_cache_section; |
741 if (type_str == switches::kRendererProcess || | 767 if (type_str == switches::kRendererProcess || |
742 type_str == switches::kPpapiPluginProcess) { | 768 type_str == switches::kPpapiPluginProcess) { |
743 if (gfx::win::ShouldUseDirectWrite()) { | 769 if (gfx::win::ShouldUseDirectWrite()) { |
744 AddDirectory(base::DIR_WINDOWS_FONTS, | 770 AddDirectory(base::DIR_WINDOWS_FONTS, |
745 NULL, | 771 NULL, |
746 true, | 772 true, |
747 sandbox::TargetPolicy::FILES_ALLOW_READONLY, | 773 sandbox::TargetPolicy::FILES_ALLOW_READONLY, |
748 policy); | 774 policy); |
749 } | 775 } |
750 } | 776 } |
751 #endif | 777 #endif |
752 | 778 |
753 if (type_str != switches::kRendererProcess) { | 779 if (type_str != switches::kRendererProcess) { |
754 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into | 780 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into |
755 // this subprocess. See | 781 // this subprocess. See |
756 // http://code.google.com/p/chromium/issues/detail?id=25580 | 782 // http://code.google.com/p/chromium/issues/detail?id=25580 |
757 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); | 783 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); |
758 } | 784 } |
759 | 785 |
760 if (!AddGenericPolicy(policy)) { | 786 result = AddGenericPolicy(policy); |
| 787 |
| 788 if (result != sandbox::SBOX_ALL_OK) { |
761 NOTREACHED(); | 789 NOTREACHED(); |
762 return base::Process(); | 790 return result; |
763 } | 791 } |
764 | 792 |
765 // Allow the renderer and gpu processes to access the log file. | 793 // Allow the renderer and gpu processes to access the log file. |
766 if (type_str == switches::kRendererProcess || | 794 if (type_str == switches::kRendererProcess || |
767 type_str == switches::kGpuProcess) { | 795 type_str == switches::kGpuProcess) { |
768 if (logging::IsLoggingToFileEnabled()) { | 796 if (logging::IsLoggingToFileEnabled()) { |
769 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); | 797 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); |
770 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 798 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
771 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 799 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
772 logging::GetLogFileFullPath().c_str()); | 800 logging::GetLogFileFullPath().c_str()); |
| 801 if (result != sandbox::SBOX_ALL_OK) |
| 802 return result; |
773 } | 803 } |
774 } | 804 } |
775 | 805 |
776 #if !defined(OFFICIAL_BUILD) | 806 #if !defined(OFFICIAL_BUILD) |
777 // If stdout/stderr point to a Windows console, these calls will | 807 // If stdout/stderr point to a Windows console, these calls will |
778 // have no effect. | 808 // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS. |
779 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); | 809 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); |
780 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); | 810 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); |
781 #endif | 811 #endif |
782 | 812 |
783 if (!delegate->PreSpawnTarget(policy)) | 813 if (!delegate->PreSpawnTarget(policy)) |
784 return base::Process(); | 814 return sandbox::SBOX_ERROR_DELEGATE_PRE_SPAWN; |
785 | 815 |
786 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 816 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
787 | 817 |
788 PROCESS_INFORMATION temp_process_info = {}; | 818 PROCESS_INFORMATION temp_process_info = {}; |
789 sandbox::ResultCode result = g_broker_services->SpawnTarget( | 819 result = g_broker_services->SpawnTarget( |
790 cmd_line->GetProgram().value().c_str(), | 820 cmd_line->GetProgram().value().c_str(), |
791 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); | 821 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); |
792 DWORD last_error = ::GetLastError(); | 822 DWORD last_error = ::GetLastError(); |
793 base::win::ScopedProcessInformation target(temp_process_info); | 823 base::win::ScopedProcessInformation target(temp_process_info); |
794 | 824 |
795 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 825 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
796 | 826 |
797 if (sandbox::SBOX_ALL_OK != result) { | 827 if (sandbox::SBOX_ALL_OK != result) { |
798 if (result == sandbox::SBOX_ERROR_GENERIC) | 828 if (result == sandbox::SBOX_ERROR_GENERIC) |
799 DPLOG(ERROR) << "Failed to launch process"; | 829 DPLOG(ERROR) << "Failed to launch process"; |
800 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { | 830 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { |
801 // TODO(shrikant): Remove this special case handling after determining | 831 // TODO(shrikant): Remove this special case handling after determining |
802 // cause for lowbox/createprocess errors. | 832 // cause for lowbox/createprocess errors. |
803 sandbox::PolicyBase* policy_base = | 833 sandbox::PolicyBase* policy_base = |
804 static_cast<sandbox::PolicyBase*>(policy); | 834 static_cast<sandbox::PolicyBase*>(policy); |
805 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? | 835 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? |
806 "Process.Sandbox.Lowbox.Launch.Error" : | 836 "Process.Sandbox.Lowbox.Launch.Error" : |
807 "Process.Sandbox.Launch.Error", | 837 "Process.Sandbox.Launch.Error", |
808 last_error); | 838 last_error); |
809 } else | 839 } else |
810 DLOG(ERROR) << "Failed to launch process. Error: " << result; | 840 DLOG(ERROR) << "Failed to launch process. Error: " << result; |
811 | 841 |
812 return base::Process(); | 842 return result; |
813 } | 843 } |
814 | 844 |
815 delegate->PostSpawnTarget(target.process_handle()); | 845 delegate->PostSpawnTarget(target.process_handle()); |
816 | 846 |
817 CHECK(ResumeThread(target.thread_handle()) != static_cast<DWORD>(-1)); | 847 CHECK(ResumeThread(target.thread_handle()) != static_cast<DWORD>(-1)); |
818 return base::Process(target.TakeProcessHandle()); | 848 *process = base::Process(target.TakeProcessHandle()); |
| 849 return sandbox::SBOX_ALL_OK; |
819 } | 850 } |
820 | 851 |
821 bool BrokerAddTargetPeer(HANDLE peer_process) { | 852 bool BrokerAddTargetPeer(HANDLE peer_process) { |
822 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; | 853 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; |
823 } | 854 } |
824 | 855 |
825 } // namespace content | 856 } // namespace content |
OLD | NEW |