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 if (!disable_default_policy && !AddPolicyForSandboxedProcess(policy)) | |
726 return base::Process(); | |
727 | 725 |
728 #if !defined(NACL_WIN64) | 726 #if !defined(NACL_WIN64) |
729 if (type_str == switches::kRendererProcess || | 727 if (type_str == switches::kRendererProcess || |
730 type_str == switches::kPpapiPluginProcess) { | 728 type_str == switches::kPpapiPluginProcess) { |
731 if (gfx::win::ShouldUseDirectWrite()) { | 729 if (gfx::win::ShouldUseDirectWrite()) { |
732 AddDirectory(base::DIR_WINDOWS_FONTS, | 730 AddDirectory(base::DIR_WINDOWS_FONTS, |
733 NULL, | 731 NULL, |
734 true, | 732 true, |
735 sandbox::TargetPolicy::FILES_ALLOW_READONLY, | 733 sandbox::TargetPolicy::FILES_ALLOW_READONLY, |
736 policy); | 734 policy); |
(...skipping 17 matching lines...) Expand all Loading... |
754 } | 752 } |
755 #endif | 753 #endif |
756 | 754 |
757 if (type_str != switches::kRendererProcess) { | 755 if (type_str != switches::kRendererProcess) { |
758 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into | 756 // Hack for Google Desktop crash. Trick GD into not injecting its DLL into |
759 // this subprocess. See | 757 // this subprocess. See |
760 // http://code.google.com/p/chromium/issues/detail?id=25580 | 758 // http://code.google.com/p/chromium/issues/detail?id=25580 |
761 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); | 759 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); |
762 } | 760 } |
763 | 761 |
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)) { | 762 if (!AddGenericPolicy(policy)) { |
781 NOTREACHED(); | 763 NOTREACHED(); |
782 return base::Process(); | 764 return base::Process(); |
783 } | 765 } |
784 | 766 |
785 // Allow the renderer and gpu processes to access the log file. | 767 // Allow the renderer and gpu processes to access the log file. |
786 if (type_str == switches::kRendererProcess || | 768 if (type_str == switches::kRendererProcess || |
787 type_str == switches::kGpuProcess) { | 769 type_str == switches::kGpuProcess) { |
788 if (logging::IsLoggingToFileEnabled()) { | 770 if (logging::IsLoggingToFileEnabled()) { |
789 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); | 771 DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute()); |
790 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 772 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
791 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 773 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
792 logging::GetLogFileFullPath().c_str()); | 774 logging::GetLogFileFullPath().c_str()); |
793 } | 775 } |
794 } | 776 } |
795 | 777 |
796 #if !defined(OFFICIAL_BUILD) | 778 #if !defined(OFFICIAL_BUILD) |
797 // If stdout/stderr point to a Windows console, these calls will | 779 // If stdout/stderr point to a Windows console, these calls will |
798 // have no effect. | 780 // have no effect. |
799 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); | 781 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); |
800 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); | 782 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); |
801 #endif | 783 #endif |
802 | 784 |
803 if (delegate) { | 785 if (!delegate->PreSpawnTarget(policy)) |
804 bool success = true; | 786 return base::Process(); |
805 delegate->PreSpawnTarget(policy, &success); | |
806 if (!success) | |
807 return base::Process(); | |
808 } | |
809 | 787 |
810 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 788 TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
811 | 789 |
812 PROCESS_INFORMATION temp_process_info = {}; | 790 PROCESS_INFORMATION temp_process_info = {}; |
813 result = g_broker_services->SpawnTarget( | 791 sandbox::ResultCode result = g_broker_services->SpawnTarget( |
814 cmd_line->GetProgram().value().c_str(), | 792 cmd_line->GetProgram().value().c_str(), |
815 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); | 793 cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); |
816 DWORD last_error = ::GetLastError(); | 794 DWORD last_error = ::GetLastError(); |
817 base::win::ScopedProcessInformation target(temp_process_info); | 795 base::win::ScopedProcessInformation target(temp_process_info); |
818 | 796 |
819 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); | 797 TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); |
820 | 798 |
821 if (sandbox::SBOX_ALL_OK != result) { | 799 if (sandbox::SBOX_ALL_OK != result) { |
822 if (result == sandbox::SBOX_ERROR_GENERIC) | 800 if (result == sandbox::SBOX_ERROR_GENERIC) |
823 DPLOG(ERROR) << "Failed to launch process"; | 801 DPLOG(ERROR) << "Failed to launch process"; |
824 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { | 802 else if (result == sandbox::SBOX_ERROR_CREATE_PROCESS) { |
825 // TODO(shrikant): Remove this special case handling after determining | 803 // TODO(shrikant): Remove this special case handling after determining |
826 // cause for lowbox/createprocess errors. | 804 // cause for lowbox/createprocess errors. |
827 sandbox::PolicyBase* policy_base = | 805 sandbox::PolicyBase* policy_base = |
828 static_cast<sandbox::PolicyBase*>(policy); | 806 static_cast<sandbox::PolicyBase*>(policy); |
829 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? | 807 UMA_HISTOGRAM_SPARSE_SLOWLY(policy_base->GetLowBoxSid() ? |
830 "Process.Sandbox.Lowbox.Launch.Error" : | 808 "Process.Sandbox.Lowbox.Launch.Error" : |
831 "Process.Sandbox.Launch.Error", | 809 "Process.Sandbox.Launch.Error", |
832 last_error); | 810 last_error); |
833 } else | 811 } else |
834 DLOG(ERROR) << "Failed to launch process. Error: " << result; | 812 DLOG(ERROR) << "Failed to launch process. Error: " << result; |
835 | 813 |
836 policy->Release(); | |
837 return base::Process(); | 814 return base::Process(); |
838 } | 815 } |
839 policy->Release(); | |
840 | 816 |
841 if (delegate) | 817 delegate->PostSpawnTarget(target.process_handle()); |
842 delegate->PostSpawnTarget(target.process_handle()); | |
843 | 818 |
844 CHECK(ResumeThread(target.thread_handle()) != -1); | 819 CHECK(ResumeThread(target.thread_handle()) != -1); |
845 return base::Process(target.TakeProcessHandle()); | 820 return base::Process(target.TakeProcessHandle()); |
846 } | 821 } |
847 | 822 |
848 bool BrokerDuplicateHandle(HANDLE source_handle, | 823 bool BrokerDuplicateHandle(HANDLE source_handle, |
849 DWORD target_process_id, | 824 DWORD target_process_id, |
850 HANDLE* target_handle, | 825 HANDLE* target_handle, |
851 DWORD desired_access, | 826 DWORD desired_access, |
852 DWORD options) { | 827 DWORD options) { |
853 // If our process is the target just duplicate the handle. | 828 // If our process is the target just duplicate the handle. |
854 if (::GetCurrentProcessId() == target_process_id) { | 829 if (::GetCurrentProcessId() == target_process_id) { |
855 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, | 830 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, |
856 ::GetCurrentProcess(), target_handle, | 831 ::GetCurrentProcess(), target_handle, |
857 desired_access, FALSE, options); | 832 desired_access, FALSE, options); |
858 | |
859 } | 833 } |
860 | 834 |
861 // Try the broker next | 835 // Try the broker next |
862 if (g_target_services && | 836 if (g_target_services && |
863 g_target_services->DuplicateHandle(source_handle, target_process_id, | 837 g_target_services->DuplicateHandle(source_handle, target_process_id, |
864 target_handle, desired_access, | 838 target_handle, desired_access, |
865 options) == sandbox::SBOX_ALL_OK) { | 839 options) == sandbox::SBOX_ALL_OK) { |
866 return true; | 840 return true; |
867 } | 841 } |
868 | 842 |
869 // Finally, see if we already have access to the process. | 843 // Finally, see if we already have access to the process. |
870 base::win::ScopedHandle target_process; | 844 base::win::ScopedHandle target_process; |
871 target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, | 845 target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, |
872 target_process_id)); | 846 target_process_id)); |
873 if (target_process.IsValid()) { | 847 if (target_process.IsValid()) { |
874 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, | 848 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, |
875 target_process.Get(), target_handle, | 849 target_process.Get(), target_handle, |
876 desired_access, FALSE, options); | 850 desired_access, FALSE, options); |
877 } | 851 } |
878 | 852 |
879 return false; | 853 return false; |
880 } | 854 } |
881 | 855 |
882 bool BrokerAddTargetPeer(HANDLE peer_process) { | 856 bool BrokerAddTargetPeer(HANDLE peer_process) { |
883 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; | 857 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; |
884 } | 858 } |
885 | 859 |
886 } // namespace content | 860 } // namespace content |
OLD | NEW |