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("could not create a socket pair"); |
311 delete this; | 311 delete this; |
312 return; | 312 return; |
313 } | 313 } |
314 internal_->socket_for_renderer = pair[0]; | 314 internal_->socket_for_renderer = pair[0]; |
315 internal_->socket_for_sel_ldr = pair[1]; | 315 internal_->socket_for_sel_ldr = pair[1]; |
316 SetCloseOnExec(pair[0]); | 316 SetCloseOnExec(pair[0]); |
317 SetCloseOnExec(pair[1]); | 317 SetCloseOnExec(pair[1]); |
318 | 318 |
319 // Launch the process | 319 // Launch the process |
320 if (!LaunchSelLdr()) { | 320 if (!LaunchSelLdr()) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 if (!script.empty()) { | 386 if (!script.empty()) { |
387 cmd_line.AppendArg("--command"); | 387 cmd_line.AppendArg("--command"); |
388 cmd_line.AppendArgNative(script.value()); | 388 cmd_line.AppendArgNative(script.value()); |
389 } | 389 } |
390 return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL); | 390 return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL); |
391 } | 391 } |
392 | 392 |
393 bool NaClProcessHost::LaunchSelLdr() { | 393 bool NaClProcessHost::LaunchSelLdr() { |
394 std::string channel_id = process_->GetHost()->CreateChannel(); | 394 std::string channel_id = process_->GetHost()->CreateChannel(); |
395 if (channel_id.empty()) { | 395 if (channel_id.empty()) { |
396 LOG(ERROR) << "NaCl process launch failed: could not create channel"; | 396 SendErrorToRenderer("could not create channel"); |
397 return false; | 397 return false; |
398 } | 398 } |
399 | 399 |
400 CommandLine::StringType nacl_loader_prefix; | 400 CommandLine::StringType nacl_loader_prefix; |
401 #if defined(OS_POSIX) | 401 #if defined(OS_POSIX) |
402 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative( | 402 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative( |
403 switches::kNaClLoaderCmdPrefix); | 403 switches::kNaClLoaderCmdPrefix); |
404 #endif // defined(OS_POSIX) | 404 #endif // defined(OS_POSIX) |
405 | 405 |
406 // Build command line for nacl. | 406 // Build command line for nacl. |
(...skipping 14 matching lines...) Expand all Loading... | |
421 #endif | 421 #endif |
422 | 422 |
423 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); | 423 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); |
424 if (exe_path.empty()) | 424 if (exe_path.empty()) |
425 return false; | 425 return false; |
426 | 426 |
427 #if defined(OS_WIN) | 427 #if defined(OS_WIN) |
428 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe | 428 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe |
429 if (RunningOnWOW64()) { | 429 if (RunningOnWOW64()) { |
430 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { | 430 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { |
431 SendErrorToRenderer("could not resolve module"); | |
431 return false; | 432 return false; |
432 } | 433 } |
433 } | 434 } |
434 #endif | 435 #endif |
435 | 436 |
436 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); | 437 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); |
437 nacl::CopyNaClCommandLineArguments(cmd_line.get()); | 438 nacl::CopyNaClCommandLineArguments(cmd_line.get()); |
438 | 439 |
439 cmd_line->AppendSwitchASCII(switches::kProcessType, | 440 cmd_line->AppendSwitchASCII(switches::kProcessType, |
440 switches::kNaClLoaderProcess); | 441 switches::kNaClLoaderProcess); |
441 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | 442 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
442 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed()) | 443 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed()) |
443 cmd_line->AppendSwitch(switches::kNoErrorDialogs); | 444 cmd_line->AppendSwitch(switches::kNoErrorDialogs); |
444 | 445 |
445 if (!nacl_loader_prefix.empty()) | 446 if (!nacl_loader_prefix.empty()) |
446 cmd_line->PrependWrapper(nacl_loader_prefix); | 447 cmd_line->PrependWrapper(nacl_loader_prefix); |
447 | 448 |
448 // On Windows we might need to start the broker process to launch a new loader | 449 // On Windows we might need to start the broker process to launch a new loader |
449 #if defined(OS_WIN) | 450 #if defined(OS_WIN) |
450 if (RunningOnWOW64()) { | 451 if (RunningOnWOW64()) { |
451 if (!NaClBrokerService::GetInstance()->LaunchLoader( | 452 if (!NaClBrokerService::GetInstance()->LaunchLoader( |
452 weak_factory_.GetWeakPtr(), channel_id)) { | 453 weak_factory_.GetWeakPtr(), channel_id)) { |
453 LOG(ERROR) << "NaCl process launch failed: broker service did not launch " | 454 SendErrorToRenderer("broker service did not launch process"); |
454 "process"; | |
455 return false; | 455 return false; |
456 } | 456 } |
457 } else { | 457 } else { |
458 process_->Launch(new NaClSandboxedProcessLauncherDelegate, | 458 process_->Launch(new NaClSandboxedProcessLauncherDelegate, |
459 cmd_line.release()); | 459 cmd_line.release()); |
460 } | 460 } |
461 #elif defined(OS_POSIX) | 461 #elif defined(OS_POSIX) |
462 process_->Launch(nacl_loader_prefix.empty(), // use_zygote | 462 process_->Launch(nacl_loader_prefix.empty(), // use_zygote |
463 base::EnvironmentVector(), | 463 base::EnvironmentVector(), |
464 cmd_line.release()); | 464 cmd_line.release()); |
(...skipping 24 matching lines...) Expand all Loading... | |
489 | 489 |
490 void NaClProcessHost::OnProcessLaunched() { | 490 void NaClProcessHost::OnProcessLaunched() { |
491 if (!StartWithLaunchedProcess()) | 491 if (!StartWithLaunchedProcess()) |
492 delete this; | 492 delete this; |
493 } | 493 } |
494 | 494 |
495 // Called when the NaClBrowser singleton has been fully initialized. | 495 // Called when the NaClBrowser singleton has been fully initialized. |
496 void NaClProcessHost::OnResourcesReady() { | 496 void NaClProcessHost::OnResourcesReady() { |
497 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 497 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
498 if (!nacl_browser->IsReady()) { | 498 if (!nacl_browser->IsReady()) { |
499 LOG(ERROR) << "NaCl process launch failed: could not acquire shared " | 499 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); |
500 "resources needed by NaCl"; | |
501 delete this; | 500 delete this; |
502 } else if (!SendStart()) { | 501 } else if (!SendStart()) { |
503 delete this; | 502 delete this; |
504 } | 503 } |
505 } | 504 } |
506 | 505 |
507 bool NaClProcessHost::ReplyToRenderer( | 506 bool NaClProcessHost::ReplyToRenderer( |
508 const IPC::ChannelHandle& channel_handle) { | 507 const IPC::ChannelHandle& channel_handle) { |
509 nacl::FileDescriptor handle_for_renderer; | 508 nacl::FileDescriptor handle_for_renderer; |
510 #if defined(OS_WIN) | 509 #if defined(OS_WIN) |
511 // Copy the handle into the renderer process. | 510 // Copy the handle into the renderer process. |
512 HANDLE handle_in_renderer; | 511 HANDLE handle_in_renderer; |
513 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 512 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
514 reinterpret_cast<HANDLE>( | 513 reinterpret_cast<HANDLE>( |
515 internal_->socket_for_renderer), | 514 internal_->socket_for_renderer), |
516 nacl_host_message_filter_->peer_handle(), | 515 nacl_host_message_filter_->peer_handle(), |
517 &handle_in_renderer, | 516 &handle_in_renderer, |
518 0, // Unused given DUPLICATE_SAME_ACCESS. | 517 0, // Unused given DUPLICATE_SAME_ACCESS. |
519 FALSE, | 518 FALSE, |
520 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 519 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
521 LOG(ERROR) << "DuplicateHandle() failed"; | 520 SendErrorToRenderer("DuplicateHandle() failed"); |
522 return false; | 521 return false; |
523 } | 522 } |
524 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( | 523 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( |
525 handle_in_renderer); | 524 handle_in_renderer); |
526 #else | 525 #else |
527 // No need to dup the imc_handle - we don't pass it anywhere else so | 526 // No need to dup the imc_handle - we don't pass it anywhere else so |
528 // it cannot be closed. | 527 // it cannot be closed. |
529 nacl::FileDescriptor imc_handle; | 528 nacl::FileDescriptor imc_handle; |
530 imc_handle.fd = internal_->socket_for_renderer; | 529 imc_handle.fd = internal_->socket_for_renderer; |
531 imc_handle.auto_close = true; | 530 imc_handle.auto_close = true; |
532 handle_for_renderer = imc_handle; | 531 handle_for_renderer = imc_handle; |
533 #endif | 532 #endif |
534 | 533 |
535 #if defined(OS_WIN) | 534 #if defined(OS_WIN) |
536 // If we are on 64-bit Windows, the NaCl process's sandbox is | 535 // If we are on 64-bit Windows, the NaCl process's sandbox is |
537 // managed by a different process from the renderer's sandbox. We | 536 // managed by a different process from the renderer's sandbox. We |
538 // need to inform the renderer's sandbox about the NaCl process so | 537 // need to inform the renderer's sandbox about the NaCl process so |
539 // that the renderer can send handles to the NaCl process using | 538 // that the renderer can send handles to the NaCl process using |
540 // BrokerDuplicateHandle(). | 539 // BrokerDuplicateHandle(). |
541 if (RunningOnWOW64()) { | 540 if (RunningOnWOW64()) { |
542 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 541 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
543 LOG(ERROR) << "Failed to add NaCl process PID"; | 542 SendErrorToRenderer("Failed to add NaCl process PID"); |
dmichael (off chromium)
2013/07/10 17:07:20
nit: let's make the capitalization consistent. Her
halyavin
2013/07/11 09:03:36
Done.
| |
544 return false; | 543 return false; |
545 } | 544 } |
546 } | 545 } |
547 #endif | 546 #endif |
548 | 547 |
549 const ChildProcessData& data = process_->GetData(); | 548 const ChildProcessData& data = process_->GetData(); |
550 NaClHostMsg_LaunchNaCl::WriteReplyParams( | 549 NaClHostMsg_LaunchNaCl::WriteReplyParams( |
dmichael (off chromium)
2013/07/10 17:07:20
For the sake of making the code more self-document
halyavin
2013/07/11 09:03:36
We are passing actual data here instead of empty n
dmichael (off chromium)
2013/07/11 16:12:59
I know, I'm suggesting you add an argument to Send
| |
551 reply_msg_, handle_for_renderer, | 550 reply_msg_, |
552 channel_handle, base::GetProcId(data.handle), data.id); | 551 nacl::NaClLaunchResult(handle_for_renderer, |
552 channel_handle, | |
553 base::GetProcId(data.handle), | |
554 data.id), | |
555 std::string()); | |
dmichael (off chromium)
2013/07/10 17:07:20
an inline comment might be nice "std::string() /*
halyavin
2013/07/11 09:03:36
Done.
| |
553 nacl_host_message_filter_->Send(reply_msg_); | 556 nacl_host_message_filter_->Send(reply_msg_); |
554 nacl_host_message_filter_ = NULL; | 557 nacl_host_message_filter_ = NULL; |
555 reply_msg_ = NULL; | 558 reply_msg_ = NULL; |
556 internal_->socket_for_renderer = NACL_INVALID_HANDLE; | 559 internal_->socket_for_renderer = NACL_INVALID_HANDLE; |
dmichael (off chromium)
2013/07/10 17:07:20
^^^ You're currently not doing this for the error
halyavin
2013/07/11 09:03:36
Yes, this is done on purpose. The handle is set to
halyavin
2013/07/11 12:49:44
The handle leak fix is here: https://codereview.ch
dmichael (off chromium)
2013/07/11 16:12:59
If we're sending a message to the other process on
| |
557 return true; | 560 return true; |
558 } | 561 } |
559 | 562 |
563 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { | |
564 LOG(ERROR) << "NaCl process launch failed: " << error_message; | |
565 if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) { | |
566 NaClHostMsg_LaunchNaCl::WriteReplyParams( | |
567 reply_msg_, nacl::NaClLaunchResult(), error_message); | |
568 nacl_host_message_filter_->Send(reply_msg_); | |
569 nacl_host_message_filter_ = NULL; | |
570 reply_msg_ = NULL; | |
571 } | |
572 } | |
573 | |
560 // TCP port we chose for NaCl debug stub. It can be any other number. | 574 // TCP port we chose for NaCl debug stub. It can be any other number. |
561 static const int kDebugStubPort = 4014; | 575 static const int kDebugStubPort = 4014; |
562 | 576 |
563 #if defined(OS_POSIX) | 577 #if defined(OS_POSIX) |
564 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { | 578 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { |
565 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 579 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
566 SocketDescriptor s; | 580 SocketDescriptor s; |
567 // We allocate currently unused TCP port for debug stub tests. The port | 581 // We allocate currently unused TCP port for debug stub tests. The port |
568 // number is passed to the test via debug stub port listener. | 582 // number is passed to the test via debug stub port listener. |
569 if (nacl_browser->HasGdbDebugStubPortListener()) { | 583 if (nacl_browser->HasGdbDebugStubPortListener()) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
748 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 762 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
749 | 763 |
750 if (nacl_browser->IsReady()) { | 764 if (nacl_browser->IsReady()) { |
751 return SendStart(); | 765 return SendStart(); |
752 } else if (nacl_browser->IsOk()) { | 766 } else if (nacl_browser->IsOk()) { |
753 nacl_browser->WaitForResources( | 767 nacl_browser->WaitForResources( |
754 base::Bind(&NaClProcessHost::OnResourcesReady, | 768 base::Bind(&NaClProcessHost::OnResourcesReady, |
755 weak_factory_.GetWeakPtr())); | 769 weak_factory_.GetWeakPtr())); |
756 return true; | 770 return true; |
757 } else { | 771 } else { |
758 LOG(ERROR) << "NaCl process failed to launch: previously failed to acquire " | 772 SendErrorToRenderer("previously failed to acquire shared resources"); |
759 "shared resources"; | |
760 return false; | 773 return false; |
761 } | 774 } |
762 } | 775 } |
763 | 776 |
764 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, | 777 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, |
765 bool* result) { | 778 bool* result) { |
766 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 779 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
767 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); | 780 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); |
768 } | 781 } |
769 | 782 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
912 } else { | 925 } else { |
913 NaClStartDebugExceptionHandlerThread( | 926 NaClStartDebugExceptionHandlerThread( |
914 process_handle.Take(), info, | 927 process_handle.Take(), info, |
915 base::MessageLoopProxy::current(), | 928 base::MessageLoopProxy::current(), |
916 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 929 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
917 weak_factory_.GetWeakPtr())); | 930 weak_factory_.GetWeakPtr())); |
918 return true; | 931 return true; |
919 } | 932 } |
920 } | 933 } |
921 #endif | 934 #endif |
OLD | NEW |