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 "chrome/browser/nacl_host/nacl_process_host.h" | 5 #include "chrome/browser/nacl_host/nacl_process_host.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 const base::FilePath& manifest_path) { | 282 const base::FilePath& manifest_path) { |
| 283 nacl_host_message_filter_ = nacl_host_message_filter; | 283 nacl_host_message_filter_ = nacl_host_message_filter; |
| 284 reply_msg_ = reply_msg; | 284 reply_msg_ = reply_msg; |
| 285 manifest_path_ = manifest_path; | 285 manifest_path_ = manifest_path; |
| 286 | 286 |
| 287 // Start getting the IRT open asynchronously while we launch the NaCl process. | 287 // Start getting the IRT open asynchronously while we launch the NaCl process. |
| 288 // We'll make sure this actually finished in StartWithLaunchedProcess, below. | 288 // We'll make sure this actually finished in StartWithLaunchedProcess, below. |
| 289 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 289 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 290 nacl_browser->EnsureAllResourcesAvailable(); | 290 nacl_browser->EnsureAllResourcesAvailable(); |
| 291 if (!nacl_browser->IsOk()) { | 291 if (!nacl_browser->IsOk()) { |
| 292 LOG(ERROR) << "NaCl process launch failed: could not find all the " | 292 SendErrorToRenderer("could not find all the resources needed" |
| 293 "resources needed to launch the process"; | 293 " to launch the process"); |
| 294 delete this; | 294 delete this; |
| 295 return; | 295 return; |
| 296 } | 296 } |
| 297 | 297 |
| 298 // Rather than creating a socket pair in the renderer, and passing | 298 // Rather than creating a socket pair in the renderer, and passing |
| 299 // one side through the browser to sel_ldr, socket pairs are created | 299 // one side through the browser to sel_ldr, socket pairs are created |
| 300 // in the browser and then passed to the renderer and sel_ldr. | 300 // in the browser and then passed to the renderer and sel_ldr. |
| 301 // | 301 // |
| 302 // This is mainly for the benefit of Windows, where sockets cannot | 302 // This is mainly for the benefit of Windows, where sockets cannot |
| 303 // be passed in messages, but are copied via DuplicateHandle(). | 303 // be passed in messages, but are copied via DuplicateHandle(). |
| 304 // This means the sandboxed renderer cannot send handles to the | 304 // This means the sandboxed renderer cannot send handles to the |
| 305 // browser process. | 305 // browser process. |
| 306 | 306 |
| 307 NaClHandle pair[2]; | 307 NaClHandle pair[2]; |
| 308 // Create a connected socket | 308 // Create a connected socket |
| 309 if (NaClSocketPair(pair) == -1) { | 309 if (NaClSocketPair(pair) == -1) { |
| 310 LOG(ERROR) << "NaCl process launch failed: could not create a socket pair"; | 310 SendErrorToRenderer("internal error: could not create a channel" |
|
Mark Seaborn
2013/07/17 18:21:49
This error message is actually misleading. NaClSo
halyavin
2013/07/18 09:32:22
Done.
| |
| 311 " between NaCl and renderer"); | |
| 311 delete this; | 312 delete this; |
| 312 return; | 313 return; |
| 313 } | 314 } |
| 314 internal_->socket_for_renderer = pair[0]; | 315 internal_->socket_for_renderer = pair[0]; |
| 315 internal_->socket_for_sel_ldr = pair[1]; | 316 internal_->socket_for_sel_ldr = pair[1]; |
| 316 SetCloseOnExec(pair[0]); | 317 SetCloseOnExec(pair[0]); |
| 317 SetCloseOnExec(pair[1]); | 318 SetCloseOnExec(pair[1]); |
| 318 | 319 |
| 319 // Launch the process | 320 // Launch the process |
| 320 if (!LaunchSelLdr()) { | 321 if (!LaunchSelLdr()) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 if (!script.empty()) { | 387 if (!script.empty()) { |
| 387 cmd_line.AppendArg("--command"); | 388 cmd_line.AppendArg("--command"); |
| 388 cmd_line.AppendArgNative(script.value()); | 389 cmd_line.AppendArgNative(script.value()); |
| 389 } | 390 } |
| 390 return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL); | 391 return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL); |
| 391 } | 392 } |
| 392 | 393 |
| 393 bool NaClProcessHost::LaunchSelLdr() { | 394 bool NaClProcessHost::LaunchSelLdr() { |
| 394 std::string channel_id = process_->GetHost()->CreateChannel(); | 395 std::string channel_id = process_->GetHost()->CreateChannel(); |
| 395 if (channel_id.empty()) { | 396 if (channel_id.empty()) { |
| 396 LOG(ERROR) << "NaCl process launch failed: could not create channel"; | 397 SendErrorToRenderer("could not create IPC channel to NaCl process"); |
|
Mark Seaborn
2013/07/17 18:21:49
Also misleading since it does not connect the IPC
halyavin
2013/07/18 09:32:22
Done.
| |
| 397 return false; | 398 return false; |
| 398 } | 399 } |
| 399 | 400 |
| 400 CommandLine::StringType nacl_loader_prefix; | 401 CommandLine::StringType nacl_loader_prefix; |
| 401 #if defined(OS_POSIX) | 402 #if defined(OS_POSIX) |
| 402 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative( | 403 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative( |
| 403 switches::kNaClLoaderCmdPrefix); | 404 switches::kNaClLoaderCmdPrefix); |
| 404 #endif // defined(OS_POSIX) | 405 #endif // defined(OS_POSIX) |
| 405 | 406 |
| 406 // Build command line for nacl. | 407 // Build command line for nacl. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 421 #endif | 422 #endif |
| 422 | 423 |
| 423 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); | 424 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); |
| 424 if (exe_path.empty()) | 425 if (exe_path.empty()) |
| 425 return false; | 426 return false; |
| 426 | 427 |
| 427 #if defined(OS_WIN) | 428 #if defined(OS_WIN) |
| 428 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe | 429 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe |
| 429 if (RunningOnWOW64()) { | 430 if (RunningOnWOW64()) { |
| 430 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { | 431 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { |
| 432 SendErrorToRenderer("could not get path to nacl64.exe"); | |
| 431 return false; | 433 return false; |
| 432 } | 434 } |
| 433 } | 435 } |
| 434 #endif | 436 #endif |
| 435 | 437 |
| 436 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); | 438 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); |
| 437 nacl::CopyNaClCommandLineArguments(cmd_line.get()); | 439 nacl::CopyNaClCommandLineArguments(cmd_line.get()); |
| 438 | 440 |
| 439 cmd_line->AppendSwitchASCII(switches::kProcessType, | 441 cmd_line->AppendSwitchASCII(switches::kProcessType, |
| 440 switches::kNaClLoaderProcess); | 442 switches::kNaClLoaderProcess); |
| 441 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | 443 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
| 442 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed()) | 444 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed()) |
| 443 cmd_line->AppendSwitch(switches::kNoErrorDialogs); | 445 cmd_line->AppendSwitch(switches::kNoErrorDialogs); |
| 444 | 446 |
| 445 if (!nacl_loader_prefix.empty()) | 447 if (!nacl_loader_prefix.empty()) |
| 446 cmd_line->PrependWrapper(nacl_loader_prefix); | 448 cmd_line->PrependWrapper(nacl_loader_prefix); |
| 447 | 449 |
| 448 // On Windows we might need to start the broker process to launch a new loader | 450 // On Windows we might need to start the broker process to launch a new loader |
| 449 #if defined(OS_WIN) | 451 #if defined(OS_WIN) |
| 450 if (RunningOnWOW64()) { | 452 if (RunningOnWOW64()) { |
| 451 if (!NaClBrokerService::GetInstance()->LaunchLoader( | 453 if (!NaClBrokerService::GetInstance()->LaunchLoader( |
| 452 weak_factory_.GetWeakPtr(), channel_id)) { | 454 weak_factory_.GetWeakPtr(), channel_id)) { |
| 453 LOG(ERROR) << "NaCl process launch failed: broker service did not launch " | 455 SendErrorToRenderer("broker service did not launch process"); |
| 454 "process"; | |
| 455 return false; | 456 return false; |
| 456 } | 457 } |
| 457 } else { | 458 } else { |
| 458 process_->Launch(new NaClSandboxedProcessLauncherDelegate, | 459 process_->Launch(new NaClSandboxedProcessLauncherDelegate, |
| 459 cmd_line.release()); | 460 cmd_line.release()); |
| 460 } | 461 } |
| 461 #elif defined(OS_POSIX) | 462 #elif defined(OS_POSIX) |
| 462 process_->Launch(nacl_loader_prefix.empty(), // use_zygote | 463 process_->Launch(nacl_loader_prefix.empty(), // use_zygote |
| 463 base::EnvironmentVector(), | 464 base::EnvironmentVector(), |
| 464 cmd_line.release()); | 465 cmd_line.release()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 489 | 490 |
| 490 void NaClProcessHost::OnProcessLaunched() { | 491 void NaClProcessHost::OnProcessLaunched() { |
| 491 if (!StartWithLaunchedProcess()) | 492 if (!StartWithLaunchedProcess()) |
| 492 delete this; | 493 delete this; |
| 493 } | 494 } |
| 494 | 495 |
| 495 // Called when the NaClBrowser singleton has been fully initialized. | 496 // Called when the NaClBrowser singleton has been fully initialized. |
| 496 void NaClProcessHost::OnResourcesReady() { | 497 void NaClProcessHost::OnResourcesReady() { |
| 497 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 498 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 498 if (!nacl_browser->IsReady()) { | 499 if (!nacl_browser->IsReady()) { |
| 499 LOG(ERROR) << "NaCl process launch failed: could not acquire shared " | 500 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); |
| 500 "resources needed by NaCl"; | |
| 501 delete this; | 501 delete this; |
| 502 } else if (!SendStart()) { | 502 } else if (!SendStart()) { |
| 503 delete this; | 503 delete this; |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 bool NaClProcessHost::ReplyToRenderer( | 507 bool NaClProcessHost::ReplyToRenderer( |
| 508 const IPC::ChannelHandle& channel_handle) { | 508 const IPC::ChannelHandle& channel_handle) { |
| 509 #if defined(OS_WIN) | 509 #if defined(OS_WIN) |
| 510 // If we are on 64-bit Windows, the NaCl process's sandbox is | 510 // If we are on 64-bit Windows, the NaCl process's sandbox is |
| 511 // managed by a different process from the renderer's sandbox. We | 511 // managed by a different process from the renderer's sandbox. We |
| 512 // need to inform the renderer's sandbox about the NaCl process so | 512 // need to inform the renderer's sandbox about the NaCl process so |
| 513 // that the renderer can send handles to the NaCl process using | 513 // that the renderer can send handles to the NaCl process using |
| 514 // BrokerDuplicateHandle(). | 514 // BrokerDuplicateHandle(). |
| 515 if (RunningOnWOW64()) { | 515 if (RunningOnWOW64()) { |
| 516 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 516 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
| 517 LOG(ERROR) << "Failed to add NaCl process PID"; | 517 SendErrorToRenderer("failed to register NaCl process in sandbox system"); |
|
Mark Seaborn
2013/07/17 18:21:49
How about "BrokerAddTargetPeer() failed"?
halyavin
2013/07/18 09:32:22
Done.
| |
| 518 return false; | 518 return false; |
| 519 } | 519 } |
| 520 } | 520 } |
| 521 #endif | 521 #endif |
| 522 | 522 |
| 523 nacl::FileDescriptor handle_for_renderer; | 523 nacl::FileDescriptor handle_for_renderer; |
| 524 #if defined(OS_WIN) | 524 #if defined(OS_WIN) |
| 525 // Copy the handle into the renderer process. | 525 // Copy the handle into the renderer process. |
| 526 HANDLE handle_in_renderer; | 526 HANDLE handle_in_renderer; |
| 527 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 527 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
| 528 reinterpret_cast<HANDLE>( | 528 reinterpret_cast<HANDLE>( |
| 529 internal_->socket_for_renderer), | 529 internal_->socket_for_renderer), |
| 530 nacl_host_message_filter_->PeerHandle(), | 530 nacl_host_message_filter_->PeerHandle(), |
| 531 &handle_in_renderer, | 531 &handle_in_renderer, |
| 532 0, // Unused given DUPLICATE_SAME_ACCESS. | 532 0, // Unused given DUPLICATE_SAME_ACCESS. |
| 533 FALSE, | 533 FALSE, |
| 534 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 534 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
| 535 LOG(ERROR) << "DuplicateHandle() failed"; | 535 SendErrorToRenderer("DuplicateHandle() failed"); |
| 536 return false; | 536 return false; |
| 537 } | 537 } |
| 538 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( | 538 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( |
| 539 handle_in_renderer); | 539 handle_in_renderer); |
| 540 #else | 540 #else |
| 541 // No need to dup the imc_handle - we don't pass it anywhere else so | 541 // No need to dup the imc_handle - we don't pass it anywhere else so |
| 542 // it cannot be closed. | 542 // it cannot be closed. |
| 543 nacl::FileDescriptor imc_handle; | 543 nacl::FileDescriptor imc_handle; |
| 544 imc_handle.fd = internal_->socket_for_renderer; | 544 imc_handle.fd = internal_->socket_for_renderer; |
| 545 imc_handle.auto_close = true; | 545 imc_handle.auto_close = true; |
| 546 handle_for_renderer = imc_handle; | 546 handle_for_renderer = imc_handle; |
| 547 #endif | 547 #endif |
| 548 | 548 |
| 549 const ChildProcessData& data = process_->GetData(); | 549 const ChildProcessData& data = process_->GetData(); |
| 550 NaClHostMsg_LaunchNaCl::WriteReplyParams( | 550 SendMessageToRenderer( |
| 551 reply_msg_, handle_for_renderer, | 551 nacl::NaClLaunchResult(handle_for_renderer, |
| 552 channel_handle, base::GetProcId(data.handle), data.id); | 552 channel_handle, |
| 553 nacl_host_message_filter_->Send(reply_msg_); | 553 base::GetProcId(data.handle), |
| 554 nacl_host_message_filter_ = NULL; | 554 data.id), |
| 555 reply_msg_ = NULL; | 555 std::string() /* error_message */); |
| 556 internal_->socket_for_renderer = NACL_INVALID_HANDLE; | 556 internal_->socket_for_renderer = NACL_INVALID_HANDLE; |
| 557 return true; | 557 return true; |
| 558 } | 558 } |
| 559 | 559 |
| 560 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { | |
| 561 LOG(ERROR) << "NaCl process launch failed: " << error_message; | |
| 562 SendMessageToRenderer(nacl::NaClLaunchResult(), error_message); | |
| 563 } | |
| 564 | |
| 565 void NaClProcessHost::SendMessageToRenderer( | |
| 566 const nacl::NaClLaunchResult& result, | |
| 567 const std::string& error_message) { | |
| 568 DCHECK(nacl_host_message_filter_); | |
| 569 DCHECK(reply_msg_); | |
| 570 if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) { | |
| 571 NaClHostMsg_LaunchNaCl::WriteReplyParams( | |
| 572 reply_msg_, result, error_message); | |
| 573 nacl_host_message_filter_->Send(reply_msg_); | |
| 574 nacl_host_message_filter_ = NULL; | |
| 575 reply_msg_ = NULL; | |
| 576 } | |
| 577 } | |
| 578 | |
| 560 // TCP port we chose for NaCl debug stub. It can be any other number. | 579 // TCP port we chose for NaCl debug stub. It can be any other number. |
| 561 static const int kDebugStubPort = 4014; | 580 static const int kDebugStubPort = 4014; |
| 562 | 581 |
| 563 #if defined(OS_POSIX) | 582 #if defined(OS_POSIX) |
| 564 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { | 583 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { |
| 565 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 584 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 566 SocketDescriptor s; | 585 SocketDescriptor s; |
| 567 // We allocate currently unused TCP port for debug stub tests. The port | 586 // We allocate currently unused TCP port for debug stub tests. The port |
| 568 // number is passed to the test via debug stub port listener. | 587 // number is passed to the test via debug stub port listener. |
| 569 if (nacl_browser->HasGdbDebugStubPortListener()) { | 588 if (nacl_browser->HasGdbDebugStubPortListener()) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 767 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 749 | 768 |
| 750 if (nacl_browser->IsReady()) { | 769 if (nacl_browser->IsReady()) { |
| 751 return SendStart(); | 770 return SendStart(); |
| 752 } else if (nacl_browser->IsOk()) { | 771 } else if (nacl_browser->IsOk()) { |
| 753 nacl_browser->WaitForResources( | 772 nacl_browser->WaitForResources( |
| 754 base::Bind(&NaClProcessHost::OnResourcesReady, | 773 base::Bind(&NaClProcessHost::OnResourcesReady, |
| 755 weak_factory_.GetWeakPtr())); | 774 weak_factory_.GetWeakPtr())); |
| 756 return true; | 775 return true; |
| 757 } else { | 776 } else { |
| 758 LOG(ERROR) << "NaCl process failed to launch: previously failed to acquire " | 777 SendErrorToRenderer("previously failed to acquire shared resources"); |
| 759 "shared resources"; | |
| 760 return false; | 778 return false; |
| 761 } | 779 } |
| 762 } | 780 } |
| 763 | 781 |
| 764 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, | 782 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, |
| 765 bool* result) { | 783 bool* result) { |
| 766 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 784 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 767 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); | 785 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); |
| 768 } | 786 } |
| 769 | 787 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 } else { | 930 } else { |
| 913 NaClStartDebugExceptionHandlerThread( | 931 NaClStartDebugExceptionHandlerThread( |
| 914 process_handle.Take(), info, | 932 process_handle.Take(), info, |
| 915 base::MessageLoopProxy::current(), | 933 base::MessageLoopProxy::current(), |
| 916 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 934 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
| 917 weak_factory_.GetWeakPtr())); | 935 weak_factory_.GetWeakPtr())); |
| 918 return true; | 936 return true; |
| 919 } | 937 } |
| 920 } | 938 } |
| 921 #endif | 939 #endif |
| OLD | NEW |