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 <string> | 7 #include <string> |
8 | 8 |
9 #include "base/base_switches.h" | 9 #include "base/base_switches.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 DCHECK(target_services); | 654 DCHECK(target_services); |
655 DCHECK(!g_target_services); | 655 DCHECK(!g_target_services); |
656 sandbox::ResultCode result = target_services->Init(); | 656 sandbox::ResultCode result = target_services->Init(); |
657 g_target_services = target_services; | 657 g_target_services = target_services; |
658 return sandbox::SBOX_ALL_OK == result; | 658 return sandbox::SBOX_ALL_OK == result; |
659 } | 659 } |
660 | 660 |
661 base::Process StartSandboxedProcess( | 661 base::Process StartSandboxedProcess( |
662 SandboxedProcessLauncherDelegate* delegate, | 662 SandboxedProcessLauncherDelegate* delegate, |
663 base::CommandLine* cmd_line) { | 663 base::CommandLine* cmd_line) { |
| 664 DCHECK(delegate); |
664 const base::CommandLine& browser_command_line = | 665 const base::CommandLine& browser_command_line = |
665 *base::CommandLine::ForCurrentProcess(); | 666 *base::CommandLine::ForCurrentProcess(); |
666 std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType); | 667 std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType); |
667 | 668 |
668 TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); | 669 TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); |
669 | 670 |
670 // Propagate the --allow-no-job flag if present. | 671 // Propagate the --allow-no-job flag if present. |
671 if (browser_command_line.HasSwitch(switches::kAllowNoSandboxJob) && | 672 if (browser_command_line.HasSwitch(switches::kAllowNoSandboxJob) && |
672 !cmd_line->HasSwitch(switches::kAllowNoSandboxJob)) { | 673 !cmd_line->HasSwitch(switches::kAllowNoSandboxJob)) { |
673 cmd_line->AppendSwitch(switches::kAllowNoSandboxJob); | 674 cmd_line->AppendSwitch(switches::kAllowNoSandboxJob); |
674 } | 675 } |
675 | 676 |
676 ProcessDebugFlags(cmd_line); | 677 ProcessDebugFlags(cmd_line); |
677 | 678 |
678 // Prefetch hints on windows: | 679 // Prefetch hints on windows: |
679 // Using a different prefetch profile per process type will allow Windows | 680 // Using a different prefetch profile per process type will allow Windows |
680 // to create separate pretetch settings for browser, renderer etc. | 681 // to create separate pretetch settings for browser, renderer etc. |
681 cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", base::Hash(type_str))); | 682 cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", base::Hash(type_str))); |
682 | 683 |
683 if ((delegate && !delegate->ShouldSandbox()) || | 684 if ((!delegate->ShouldSandbox()) || |
684 browser_command_line.HasSwitch(switches::kNoSandbox) || | 685 browser_command_line.HasSwitch(switches::kNoSandbox) || |
685 cmd_line->HasSwitch(switches::kNoSandbox)) { | 686 cmd_line->HasSwitch(switches::kNoSandbox)) { |
686 base::Process process = | 687 base::Process process = |
687 base::LaunchProcess(*cmd_line, base::LaunchOptions()); | 688 base::LaunchProcess(*cmd_line, base::LaunchOptions()); |
688 // TODO(rvargas) crbug.com/417532: Don't share a raw handle. | 689 // TODO(rvargas) crbug.com/417532: Don't share a raw handle. |
689 g_broker_services->AddTargetPeer(process.Handle()); | 690 g_broker_services->AddTargetPeer(process.Handle()); |
690 return process.Pass(); | 691 return process.Pass(); |
691 } | 692 } |
692 | 693 |
693 sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy(); | 694 sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy(); |
(...skipping 16 matching lines...) Expand all Loading... |
710 #endif | 711 #endif |
711 | 712 |
712 mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS | | 713 mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS | |
713 sandbox::MITIGATION_DLL_SEARCH_ORDER; | 714 sandbox::MITIGATION_DLL_SEARCH_ORDER; |
714 | 715 |
715 if (policy->SetDelayedProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK) | 716 if (policy->SetDelayedProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK) |
716 return base::Process(); | 717 return base::Process(); |
717 | 718 |
718 SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy); | 719 SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy); |
719 | 720 |
720 bool disable_default_policy = false; | 721 if (!delegate->DisableDefaultPolicy()) { |
721 base::FilePath exposed_dir; | 722 if (!AddPolicyForSandboxedProcess(policy)) { |
722 if (delegate) | 723 return base::Process(); |
723 delegate->PreSandbox(&disable_default_policy, &exposed_dir); | 724 } |
724 | 725 } |
725 if (!disable_default_policy && !AddPolicyForSandboxedProcess(policy)) | |
726 return base::Process(); | |
727 | 726 |
728 #if !defined(NACL_WIN64) | 727 #if !defined(NACL_WIN64) |
729 if (type_str == switches::kRendererProcess || | 728 if (type_str == switches::kRendererProcess || |
730 type_str == switches::kPpapiPluginProcess) { | 729 type_str == switches::kPpapiPluginProcess) { |
731 if (gfx::win::ShouldUseDirectWrite()) { | 730 if (gfx::win::ShouldUseDirectWrite()) { |
732 AddDirectory(base::DIR_WINDOWS_FONTS, | 731 AddDirectory(base::DIR_WINDOWS_FONTS, |
733 NULL, | 732 NULL, |
734 true, | 733 true, |
735 sandbox::TargetPolicy::FILES_ALLOW_READONLY, | 734 sandbox::TargetPolicy::FILES_ALLOW_READONLY, |
736 policy); | 735 policy); |
(...skipping 17 matching lines...) Expand all Loading... |
754 } | 753 } |
755 #endif | 754 #endif |
756 | 755 |
757 if (type_str != switches::kRendererProcess) { | 756 if (type_str != switches::kRendererProcess) { |
758 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into | 757 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into |
759 // this subprocess. See | 758 // this subprocess. See |
760 // http://code.google.com/p/chromium/issues/detail?id=25580 | 759 // http://code.google.com/p/chromium/issues/detail?id=25580 |
761 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); | 760 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); |
762 } | 761 } |
763 | 762 |
764 sandbox::ResultCode result; | |
765 if (!exposed_dir.empty()) { | |
766 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | |
767 sandbox::TargetPolicy::FILES_ALLOW_ANY, | |
768 exposed_dir.value().c_str()); | |
769 if (result != sandbox::SBOX_ALL_OK) | |
770 return base::Process(); | |
771 | |
772 base::FilePath exposed_files = exposed_dir.AppendASCII("*"); | |
773 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | |
774 sandbox::TargetPolicy::FILES_ALLOW_ANY, | |
775 exposed_files.value().c_str()); | |
776 if (result != sandbox::SBOX_ALL_OK) | |
777 return base::Process(); | |
778 } | |
779 | |
780 if (!AddGenericPolicy(policy)) { | 763 if (!AddGenericPolicy(policy)) { |
781 NOTREACHED(); | 764 NOTREACHED(); |
782 return base::Process(); | 765 return base::Process(); |
783 } | 766 } |
784 | 767 |
785 // Allow the renderer and gpu processes to access the log file. | 768 // Allow the renderer and gpu processes to access the log file. |
786 if (type_str == switches::kRendererProcess || | 769 if (type_str == switches::kRendererProcess || |
787 type_str == switches::kGpuProcess) { | 770 type_str == switches::kGpuProcess) { |
788 if (logging::IsLoggingToFileEnabled()) { | 771 if (logging::IsLoggingToFileEnabled()) { |
789 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); | 772 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); |
790 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 773 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
791 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 774 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
792 logging::GetLogFileFullPath().c_str()); | 775 logging::GetLogFileFullPath().c_str()); |
793 } | 776 } |
794 } | 777 } |
795 | 778 |
796 #if !defined(OFFICIAL_BUILD) | 779 #if !defined(OFFICIAL_BUILD) |
797 // If stdout/stderr point to a Windows console, these calls will | 780 // If stdout/stderr point to a Windows console, these calls will |
798 // have no effect. | 781 // have no effect. |
799 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); | 782 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); |
800 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); | 783 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); |
801 #endif | 784 #endif |
802 | 785 |
803 if (delegate) { | 786 if (!delegate->PreSpawnTarget(policy)) { |
804 bool success = true; | 787 return base::Process(); |
805 delegate->PreSpawnTarget(policy, &success); | |
806 if (!success) | |
807 return base::Process(); | |
808 } | 788 } |
809 | 789 |
810 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 790 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
811 | 791 |
812 PROCESS_INFORMATION temp_process_info = {}; | 792 PROCESS_INFORMATION temp_process_info = {}; |
813 result = g_broker_services->SpawnTarget( | 793 sandbox::ResultCode result = g_broker_services->SpawnTarget( |
814 cmd_line->GetProgram().value().c_str(), | 794 cmd_line->GetProgram().value().c_str(), |
815 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); | 795 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); |
816 DWORD last_error = ::GetLastError(); | 796 DWORD last_error = ::GetLastError(); |
817 base::win::ScopedProcessInformation target(temp_process_info); | 797 base::win::ScopedProcessInformation target(temp_process_info); |
818 | 798 |
819 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 799 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
820 | 800 |
821 if (sandbox::SBOX_ALL_OK != result) { | 801 if (sandbox::SBOX_ALL_OK != result) { |
822 if (result == sandbox::SBOX_ERROR_GENERIC) | 802 if (result == sandbox::SBOX_ERROR_GENERIC) |
823 DPLOG(ERROR) << "Failed to launch process"; | 803 DPLOG(ERROR) << "Failed to launch process"; |
824 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { | 804 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { |
825 // TODO(shrikant): Remove this special case handling after determining | 805 // TODO(shrikant): Remove this special case handling after determining |
826 // cause for lowbox/createprocess errors. | 806 // cause for lowbox/createprocess errors. |
827 sandbox::PolicyBase* policy_base = | 807 sandbox::PolicyBase* policy_base = |
828 static_cast<sandbox::PolicyBase*>(policy); | 808 static_cast<sandbox::PolicyBase*>(policy); |
829 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? | 809 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? |
830 "Process.Sandbox.Lowbox.Launch.Error" : | 810 "Process.Sandbox.Lowbox.Launch.Error" : |
831 "Process.Sandbox.Launch.Error", | 811 "Process.Sandbox.Launch.Error", |
832 last_error); | 812 last_error); |
833 } else | 813 } else |
834 DLOG(ERROR) << "Failed to launch process. Error: " << result; | 814 DLOG(ERROR) << "Failed to launch process. Error: " << result; |
835 | 815 |
836 policy->Release(); | |
837 return base::Process(); | 816 return base::Process(); |
838 } | 817 } |
839 policy->Release(); | |
840 | 818 |
841 if (delegate) | 819 delegate->PostSpawnTarget(target.process_handle()); |
842 delegate->PostSpawnTarget(target.process_handle()); | |
843 | 820 |
844 CHECK(ResumeThread(target.thread_handle()) != -1); | 821 CHECK(ResumeThread(target.thread_handle()) != -1); |
845 return base::Process(target.TakeProcessHandle()); | 822 return base::Process(target.TakeProcessHandle()); |
846 } | 823 } |
847 | 824 |
848 bool BrokerDuplicateHandle(HANDLE source_handle, | 825 bool BrokerDuplicateHandle(HANDLE source_handle, |
849 DWORD target_process_id, | 826 DWORD target_process_id, |
850 HANDLE* target_handle, | 827 HANDLE* target_handle, |
851 DWORD desired_access, | 828 DWORD desired_access, |
852 DWORD options) { | 829 DWORD options) { |
853 // If our process is the target just duplicate the handle. | 830 // If our process is the target just duplicate the handle. |
854 if (::GetCurrentProcessId() == target_process_id) { | 831 if (::GetCurrentProcessId() == target_process_id) { |
855 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, | 832 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, |
856 ::GetCurrentProcess(), target_handle, | 833 ::GetCurrentProcess(), target_handle, |
857 desired_access, FALSE, options); | 834 desired_access, FALSE, options); |
858 | |
859 } | 835 } |
860 | 836 |
861 // Try the broker next | 837 // Try the broker next |
862 if (g_target_services && | 838 if (g_target_services && |
863 g_target_services->DuplicateHandle(source_handle, target_process_id, | 839 g_target_services->DuplicateHandle(source_handle, target_process_id, |
864 target_handle, desired_access, | 840 target_handle, desired_access, |
865 options) == sandbox::SBOX_ALL_OK) { | 841 options) == sandbox::SBOX_ALL_OK) { |
866 return true; | 842 return true; |
867 } | 843 } |
868 | 844 |
869 // Finally, see if we already have access to the process. | 845 // Finally, see if we already have access to the process. |
870 base::win::ScopedHandle target_process; | 846 base::win::ScopedHandle target_process; |
871 target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, | 847 target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, |
872 target_process_id)); | 848 target_process_id)); |
873 if (target_process.IsValid()) { | 849 if (target_process.IsValid()) { |
874 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, | 850 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, |
875 target_process.Get(), target_handle, | 851 target_process.Get(), target_handle, |
876 desired_access, FALSE, options); | 852 desired_access, FALSE, options); |
877 } | 853 } |
878 | 854 |
879 return false; | 855 return false; |
880 } | 856 } |
881 | 857 |
882 bool BrokerAddTargetPeer(HANDLE peer_process) { | 858 bool BrokerAddTargetPeer(HANDLE peer_process) { |
883 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; | 859 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; |
884 } | 860 } |
885 | 861 |
886 } // namespace content | 862 } // namespace content |
OLD | NEW |