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