Chromium Code Reviews| 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_policy.h" | 5 #include "content/common/sandbox_policy.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/debugger.h" | 10 #include "base/debug/debugger.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "content/public/common/content_client.h" | 24 #include "content/public/common/content_client.h" |
| 25 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
| 26 #include "content/public/common/process_type.h" | 26 #include "content/public/common/process_type.h" |
| 27 #include "content/public/common/sandbox_init.h" | 27 #include "content/public/common/sandbox_init.h" |
| 28 #include "sandbox/win/src/process_mitigations.h" | 28 #include "sandbox/win/src/process_mitigations.h" |
| 29 #include "sandbox/win/src/sandbox.h" | 29 #include "sandbox/win/src/sandbox.h" |
| 30 #include "sandbox/win/src/sandbox_nt_util.h" | 30 #include "sandbox/win/src/sandbox_nt_util.h" |
| 31 #include "sandbox/win/src/win_utils.h" | 31 #include "sandbox/win/src/win_utils.h" |
| 32 #include "ui/gl/gl_switches.h" | 32 #include "ui/gl/gl_switches.h" |
| 33 | 33 |
| 34 static sandbox::BrokerServices* g_broker_services = NULL; | 34 namespace content { |
| 35 static sandbox::TargetServices* g_target_services = NULL; | |
| 36 | |
| 37 namespace { | 35 namespace { |
| 36 sandbox::BrokerServices* g_broker_services = NULL; | |
| 37 sandbox::TargetServices* g_target_services = NULL; | |
| 38 base::LazyInstance<SandboxedProcessStartingCallback> | |
| 39 g_sandboxed_process_starting_callback = LAZY_INSTANCE_INITIALIZER; | |
| 38 | 40 |
| 39 // The DLLs listed here are known (or under strong suspicion) of causing crashes | 41 // The DLLs listed here are known (or under strong suspicion) of causing crashes |
| 40 // when they are loaded in the renderer. Note: at runtime we generate short | 42 // when they are loaded in the renderer. Note: at runtime we generate short |
| 41 // versions of the dll name only if the dll has an extension. | 43 // versions of the dll name only if the dll has an extension. |
| 42 const wchar_t* const kTroublesomeDlls[] = { | 44 const wchar_t* const kTroublesomeDlls[] = { |
| 43 L"adialhk.dll", // Kaspersky Internet Security. | 45 L"adialhk.dll", // Kaspersky Internet Security. |
| 44 L"acpiz.dll", // Unknown. | 46 L"acpiz.dll", // Unknown. |
| 45 L"avgrsstx.dll", // AVG 8. | 47 L"avgrsstx.dll", // AVG 8. |
| 46 L"babylonchromepi.dll", // Babylon translator. | 48 L"babylonchromepi.dll", // Babylon translator. |
| 47 L"btkeyind.dll", // Widcomm Bluetooth. | 49 L"btkeyind.dll", // Widcomm Bluetooth. |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 sandbox::ResultCode result; | 318 sandbox::ResultCode result; |
| 317 | 319 |
| 318 // Add the policy for the client side of a pipe. It is just a file | 320 // Add the policy for the client side of a pipe. It is just a file |
| 319 // in the \pipe\ namespace. We restrict it to pipes that start with | 321 // in the \pipe\ namespace. We restrict it to pipes that start with |
| 320 // "chrome." so the sandboxed process cannot connect to system services. | 322 // "chrome." so the sandboxed process cannot connect to system services. |
| 321 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 323 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
| 322 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 324 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
| 323 L"\\??\\pipe\\chrome.*"); | 325 L"\\??\\pipe\\chrome.*"); |
| 324 if (result != sandbox::SBOX_ALL_OK) | 326 if (result != sandbox::SBOX_ALL_OK) |
| 325 return false; | 327 return false; |
| 326 // Allow the server side of a pipe restricted to the "chrome.nacl." | 328 |
| 327 // namespace so that it cannot impersonate other system or other chrome | |
| 328 // service pipes. | |
| 329 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | |
| 330 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | |
| 331 L"\\\\.\\pipe\\chrome.nacl.*"); | |
| 332 if (result != sandbox::SBOX_ALL_OK) | |
| 333 return false; | |
| 334 // Allow the server side of sync sockets, which are pipes that have | 329 // Allow the server side of sync sockets, which are pipes that have |
| 335 // the "chrome.sync" namespace and a randomly generated suffix. | 330 // the "chrome.sync" namespace and a randomly generated suffix. |
| 336 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | 331 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, |
| 337 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | 332 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, |
| 338 L"\\\\.\\pipe\\chrome.sync.*"); | 333 L"\\\\.\\pipe\\chrome.sync.*"); |
| 339 if (result != sandbox::SBOX_ALL_OK) | 334 if (result != sandbox::SBOX_ALL_OK) |
| 340 return false; | 335 return false; |
| 341 | 336 |
| 342 // Add the policy for debug message only in debug | 337 // Add the policy for debug message only in debug |
| 343 #ifndef NDEBUG | 338 #ifndef NDEBUG |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 if (result != sandbox::SBOX_ALL_OK) | 465 if (result != sandbox::SBOX_ALL_OK) |
| 471 return false; | 466 return false; |
| 472 | 467 |
| 473 // Renderers need to share events with plugins. | 468 // Renderers need to share events with plugins. |
| 474 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, | 469 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, |
| 475 sandbox::TargetPolicy::HANDLES_DUP_ANY, | 470 sandbox::TargetPolicy::HANDLES_DUP_ANY, |
| 476 L"Event"); | 471 L"Event"); |
| 477 if (result != sandbox::SBOX_ALL_OK) | 472 if (result != sandbox::SBOX_ALL_OK) |
| 478 return false; | 473 return false; |
| 479 | 474 |
| 480 // Renderers need to send named pipe handles and shared memory | |
| 481 // segment handles to NaCl loader processes. | |
| 482 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, | |
| 483 sandbox::TargetPolicy::HANDLES_DUP_ANY, | |
| 484 L"File"); | |
| 485 if (result != sandbox::SBOX_ALL_OK) | |
| 486 return false; | |
| 487 | |
| 488 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; | 475 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; |
| 489 if (base::win::GetVersion() > base::win::VERSION_XP) { | 476 if (base::win::GetVersion() > base::win::VERSION_XP) { |
| 490 // On 2003/Vista the initial token has to be restricted if the main | 477 // On 2003/Vista the initial token has to be restricted if the main |
| 491 // token is restricted. | 478 // token is restricted. |
| 492 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; | 479 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; |
| 493 } | 480 } |
| 494 | 481 |
| 495 policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); | 482 policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); |
| 496 // Prevents the renderers from manipulating low-integrity processes. | 483 // Prevents the renderers from manipulating low-integrity processes. |
| 497 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED); | 484 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 // Callers use CHECK macro to make sure we get the right stack. | 598 // Callers use CHECK macro to make sure we get the right stack. |
| 612 CheckDuplicateHandle(handle); | 599 CheckDuplicateHandle(handle); |
| 613 } | 600 } |
| 614 | 601 |
| 615 return TRUE; | 602 return TRUE; |
| 616 } | 603 } |
| 617 #endif | 604 #endif |
| 618 | 605 |
| 619 } // namespace | 606 } // namespace |
| 620 | 607 |
| 621 namespace content { | |
| 622 | |
| 623 bool InitBrokerServices(sandbox::BrokerServices* broker_services) { | 608 bool InitBrokerServices(sandbox::BrokerServices* broker_services) { |
| 624 // TODO(abarth): DCHECK(CalledOnValidThread()); | 609 // TODO(abarth): DCHECK(CalledOnValidThread()); |
| 625 // See <http://b/1287166>. | 610 // See <http://b/1287166>. |
| 626 DCHECK(broker_services); | 611 DCHECK(broker_services); |
| 627 DCHECK(!g_broker_services); | 612 DCHECK(!g_broker_services); |
| 628 sandbox::ResultCode result = broker_services->Init(); | 613 sandbox::ResultCode result = broker_services->Init(); |
| 629 g_broker_services = broker_services; | 614 g_broker_services = broker_services; |
| 630 | 615 |
| 631 // In non-official builds warn about dangerous uses of DuplicateHandle. | 616 // In non-official builds warn about dangerous uses of DuplicateHandle. |
| 632 BOOL is_in_job = FALSE; | 617 BOOL is_in_job = FALSE; |
| 633 #ifdef NACL_WIN64 | 618 #ifdef NACL_WIN64 |
| 634 CHECK(::IsProcessInJob(::GetCurrentProcess(), NULL, &is_in_job)); | 619 CHECK(::IsProcessInJob(::GetCurrentProcess(), NULL, &is_in_job)); |
| 635 #endif | 620 #endif |
| 636 #ifndef OFFICIAL_BUILD | 621 #ifndef OFFICIAL_BUILD |
| 637 if (!is_in_job && !g_iat_patch_duplicate_handle.is_patched()) { | 622 if (!is_in_job && !g_iat_patch_duplicate_handle.is_patched()) { |
| 638 HMODULE module = NULL; | 623 HMODULE module = NULL; |
| 639 wchar_t module_name[MAX_PATH]; | 624 wchar_t module_name[MAX_PATH]; |
| 640 CHECK(::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | 625 CHECK(::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, |
| 641 reinterpret_cast<LPCWSTR>(InitBrokerServices), | 626 reinterpret_cast<LPCWSTR>(InitBrokerServices), |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 exposed_files.value().c_str()); | 798 exposed_files.value().c_str()); |
| 814 if (result != sandbox::SBOX_ALL_OK) | 799 if (result != sandbox::SBOX_ALL_OK) |
| 815 return 0; | 800 return 0; |
| 816 } | 801 } |
| 817 | 802 |
| 818 if (!AddGenericPolicy(policy)) { | 803 if (!AddGenericPolicy(policy)) { |
| 819 NOTREACHED(); | 804 NOTREACHED(); |
| 820 return 0; | 805 return 0; |
| 821 } | 806 } |
| 822 | 807 |
| 808 if (!g_sandboxed_process_starting_callback.Pointer()->is_null()) { | |
| 809 g_sandboxed_process_starting_callback.Pointer()->Run( | |
| 810 cmd_line, policy); | |
| 811 } | |
| 812 | |
| 823 if (browser_command_line.HasSwitch(switches::kEnableLogging)) { | 813 if (browser_command_line.HasSwitch(switches::kEnableLogging)) { |
| 824 // If stdout/stderr point to a Windows console, these calls will | 814 // If stdout/stderr point to a Windows console, these calls will |
| 825 // have no effect. | 815 // have no effect. |
| 826 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); | 816 policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); |
| 827 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); | 817 policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); |
| 828 } | 818 } |
| 829 | 819 |
| 830 TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); | 820 TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); |
| 831 | 821 |
| 832 result = g_broker_services->SpawnTarget( | 822 result = g_broker_services->SpawnTarget( |
| 833 cmd_line->GetProgram().value().c_str(), | 823 cmd_line->GetProgram().value().c_str(), |
| 834 cmd_line->GetCommandLineString().c_str(), | 824 cmd_line->GetCommandLineString().c_str(), |
| 835 policy, target.Receive()); | 825 policy, target.Receive()); |
| 836 policy->Release(); | 826 policy->Release(); |
| 837 | 827 |
| 838 TRACE_EVENT_END_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); | 828 TRACE_EVENT_END_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); |
| 839 | 829 |
| 840 if (sandbox::SBOX_ALL_OK != result) { | 830 if (sandbox::SBOX_ALL_OK != result) { |
| 841 DLOG(ERROR) << "Failed to launch process. Error: " << result; | 831 DLOG(ERROR) << "Failed to launch process. Error: " << result; |
| 842 return 0; | 832 return 0; |
| 843 } | 833 } |
| 844 | 834 |
| 845 #if !defined(NACL_WIN64) | 835 #if !defined(NACL_WIN64) |
| 846 // For Native Client sel_ldr processes on 32-bit Windows, reserve 1 GB of | 836 // For Native Client sel_ldr processes on 32-bit Windows, reserve 1 GB of |
|
cpu_(ooo_6.6-7.5)
2013/03/18 19:46:26
you want to add this as another callback after pro
jam
2013/03/18 19:50:19
yeah, this and other nacl stuff in this file will
| |
| 847 // address space to prevent later failure due to address space fragmentation | 837 // address space to prevent later failure due to address space fragmentation |
| 848 // from .dll loading. The NaCl process will attempt to locate this space by | 838 // from .dll loading. The NaCl process will attempt to locate this space by |
| 849 // scanning the address space using VirtualQuery. | 839 // scanning the address space using VirtualQuery. |
| 850 // TODO(bbudge) Handle the --no-sandbox case. | 840 // TODO(bbudge) Handle the --no-sandbox case. |
| 851 // http://code.google.com/p/nativeclient/issues/detail?id=2131 | 841 // http://code.google.com/p/nativeclient/issues/detail?id=2131 |
| 852 if (type == PROCESS_TYPE_NACL_LOADER) { | 842 if (type == PROCESS_TYPE_NACL_LOADER) { |
| 853 const SIZE_T kOneGigabyte = 1 << 30; | 843 const SIZE_T kOneGigabyte = 1 << 30; |
| 854 void* nacl_mem = VirtualAllocEx(target.process_handle(), | 844 void* nacl_mem = VirtualAllocEx(target.process_handle(), |
| 855 NULL, | 845 NULL, |
| 856 kOneGigabyte, | 846 kOneGigabyte, |
| 857 MEM_RESERVE, | 847 MEM_RESERVE, |
| 858 PAGE_NOACCESS); | 848 PAGE_NOACCESS); |
| 859 if (!nacl_mem) { | 849 if (!nacl_mem) { |
| 860 DLOG(WARNING) << "Failed to reserve address space for Native Client"; | 850 DLOG(WARNING) << "Failed to reserve address space for Native Client"; |
| 861 } | 851 } |
| 862 } | 852 } |
| 863 #endif // !defined(NACL_WIN64) | 853 #endif // !defined(NACL_WIN64) |
| 864 | 854 |
| 865 ResumeThread(target.thread_handle()); | 855 ResumeThread(target.thread_handle()); |
| 866 | 856 |
| 867 // Help the process a little. It can't start the debugger by itself if | 857 // Help the process a little. It can't start the debugger by itself if |
| 868 // the process is in a sandbox. | 858 // the process is in a sandbox. |
| 869 if (child_needs_help) | 859 if (child_needs_help) |
| 870 base::debug::SpawnDebuggerOnProcess(target.process_id()); | 860 base::debug::SpawnDebuggerOnProcess(target.process_id()); |
| 871 | 861 |
| 872 return target.TakeProcessHandle(); | 862 return target.TakeProcessHandle(); |
| 873 } | 863 } |
| 874 | 864 |
| 865 void SetSandboxedProcessStartingCallback( | |
| 866 const SandboxedProcessStartingCallback& callback) { | |
| 867 g_sandboxed_process_starting_callback.Get() = callback; | |
| 868 } | |
| 869 | |
| 875 bool BrokerDuplicateHandle(HANDLE source_handle, | 870 bool BrokerDuplicateHandle(HANDLE source_handle, |
| 876 DWORD target_process_id, | 871 DWORD target_process_id, |
| 877 HANDLE* target_handle, | 872 HANDLE* target_handle, |
| 878 DWORD desired_access, | 873 DWORD desired_access, |
| 879 DWORD options) { | 874 DWORD options) { |
| 880 // If our process is the target just duplicate the handle. | 875 // If our process is the target just duplicate the handle. |
| 881 if (::GetCurrentProcessId() == target_process_id) { | 876 if (::GetCurrentProcessId() == target_process_id) { |
| 882 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, | 877 return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, |
| 883 ::GetCurrentProcess(), target_handle, | 878 ::GetCurrentProcess(), target_handle, |
| 884 desired_access, FALSE, options); | 879 desired_access, FALSE, options); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 904 } | 899 } |
| 905 | 900 |
| 906 return false; | 901 return false; |
| 907 } | 902 } |
| 908 | 903 |
| 909 bool BrokerAddTargetPeer(HANDLE peer_process) { | 904 bool BrokerAddTargetPeer(HANDLE peer_process) { |
| 910 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; | 905 return g_broker_services->AddTargetPeer(peer_process) == sandbox::SBOX_ALL_OK; |
| 911 } | 906 } |
| 912 | 907 |
| 913 } // namespace content | 908 } // namespace content |
| OLD | NEW |