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