| 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 |