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 <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 | 94 |
| 95 void SetCloseOnExec(nacl::Handle fd) { | 95 void SetCloseOnExec(nacl::Handle fd) { |
| 96 #if defined(OS_POSIX) | 96 #if defined(OS_POSIX) |
| 97 int flags = fcntl(fd, F_GETFD); | 97 int flags = fcntl(fd, F_GETFD); |
| 98 CHECK_NE(flags, -1); | 98 CHECK_NE(flags, -1); |
| 99 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); | 99 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| 100 CHECK_EQ(rc, 0); | 100 CHECK_EQ(rc, 0); |
| 101 #endif | 101 #endif |
| 102 } | 102 } |
| 103 | 103 |
| 104 bool SendHandleToSelLdr( | 104 bool ShareHandleToSelLdr( |
| 105 base::ProcessHandle processh, | 105 base::ProcessHandle processh, |
| 106 nacl::Handle sourceh, | 106 nacl::Handle sourceh, |
| 107 bool close_source, | 107 bool close_source, |
| 108 std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { | 108 std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { |
| 109 #if defined(OS_WIN) | 109 #if defined(OS_WIN) |
| 110 HANDLE channel; | 110 HANDLE channel; |
| 111 int flags = DUPLICATE_SAME_ACCESS; | 111 int flags = DUPLICATE_SAME_ACCESS; |
| 112 if (close_source) | 112 if (close_source) |
| 113 flags |= DUPLICATE_CLOSE_SOURCE; | 113 flags |= DUPLICATE_CLOSE_SOURCE; |
| 114 if (!DuplicateHandle(GetCurrentProcess(), | 114 if (!DuplicateHandle(GetCurrentProcess(), |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 873 | 873 |
| 874 // The asynchronous attempt to get the IRT file open has completed. | 874 // The asynchronous attempt to get the IRT file open has completed. |
| 875 void NaClProcessHost::IrtReady() { | 875 void NaClProcessHost::IrtReady() { |
| 876 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 876 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 877 if (!nacl_browser->IrtAvailable() || !SendStart()) { | 877 if (!nacl_browser->IrtAvailable() || !SendStart()) { |
| 878 DLOG(ERROR) << "Cannot launch NaCl process"; | 878 DLOG(ERROR) << "Cannot launch NaCl process"; |
| 879 delete this; | 879 delete this; |
| 880 } | 880 } |
| 881 } | 881 } |
| 882 | 882 |
| 883 bool NaClProcessHost::SendStart() { | 883 bool NaClProcessHost::StartNaClExecution() { |
|
Mark Seaborn
2012/04/07 00:23:34
The ordering of the file would be more logical if
| |
| 884 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 884 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 885 | |
| 886 nacl::NaClStartParams params; | |
| 887 params.validation_cache_key = nacl_browser->GetValidatorCacheKey(); | |
| 888 params.version = chrome::VersionInfo().CreateVersionString(); | |
| 889 params.enable_exception_handling = enable_exception_handling_; | |
| 890 | |
| 885 base::PlatformFile irt_file = nacl_browser->IrtFile(); | 891 base::PlatformFile irt_file = nacl_browser->IrtFile(); |
| 886 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); | 892 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); |
| 887 | 893 |
| 894 const ChildProcessData& data = process_->GetData(); | |
| 895 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | |
| 896 if (!ShareHandleToSelLdr(data.handle, | |
| 897 internal_->sockets_for_sel_ldr[i], true, | |
| 898 ¶ms.handles)) { | |
| 899 return false; | |
| 900 } | |
| 901 } | |
| 902 | |
| 903 // Send over the IRT file handle. We don't close our own copy! | |
| 904 if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) | |
| 905 return false; | |
| 906 | |
| 907 #if defined(OS_MACOSX) | |
| 908 // For dynamic loading support, NaCl requires a file descriptor that | |
| 909 // was created in /tmp, since those created with shm_open() are not | |
| 910 // mappable with PROT_EXEC. Rather than requiring an extra IPC | |
| 911 // round trip out of the sandbox, we create an FD here. | |
| 912 base::SharedMemory memory_buffer; | |
| 913 base::SharedMemoryCreateOptions options; | |
| 914 options.size = 1; | |
| 915 options.executable = true; | |
| 916 if (!memory_buffer.Create(options)) { | |
| 917 DLOG(ERROR) << "Failed to allocate memory buffer"; | |
| 918 return false; | |
| 919 } | |
| 920 nacl::FileDescriptor memory_fd; | |
| 921 memory_fd.fd = dup(memory_buffer.handle().fd); | |
| 922 if (memory_fd.fd < 0) { | |
| 923 DLOG(ERROR) << "Failed to dup() a file descriptor"; | |
| 924 return false; | |
| 925 } | |
| 926 memory_fd.auto_close = true; | |
| 927 params.handles.push_back(memory_fd); | |
| 928 #endif | |
| 929 | |
| 930 IPC::Message* start_message = new NaClProcessMsg_Start(params); | |
| 931 #if defined(OS_WIN) | |
| 932 if (debug_context_ != NULL) { | |
| 933 debug_context_->SetStartMessage(start_message); | |
| 934 debug_context_->SendStartMessage(); | |
| 935 } else { | |
| 936 process_->Send(start_message); | |
| 937 } | |
| 938 #else | |
| 939 process_->Send(start_message); | |
| 940 #endif | |
| 941 | |
| 942 internal_->sockets_for_sel_ldr.clear(); | |
| 943 return true; | |
| 944 } | |
| 945 | |
| 946 bool NaClProcessHost::ReplyToRenderer() { | |
| 888 std::vector<nacl::FileDescriptor> handles_for_renderer; | 947 std::vector<nacl::FileDescriptor> handles_for_renderer; |
| 889 base::ProcessHandle nacl_process_handle; | |
| 890 | |
| 891 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | 948 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { |
| 892 #if defined(OS_WIN) | 949 #if defined(OS_WIN) |
| 893 // Copy the handle into the renderer process. | 950 // Copy the handle into the renderer process. |
| 894 HANDLE handle_in_renderer; | 951 HANDLE handle_in_renderer; |
| 895 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 952 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
| 896 reinterpret_cast<HANDLE>( | 953 reinterpret_cast<HANDLE>( |
| 897 internal_->sockets_for_renderer[i]), | 954 internal_->sockets_for_renderer[i]), |
| 898 chrome_render_message_filter_->peer_handle(), | 955 chrome_render_message_filter_->peer_handle(), |
| 899 &handle_in_renderer, | 956 &handle_in_renderer, |
| 900 0, // Unused given DUPLICATE_SAME_ACCESS. | 957 0, // Unused given DUPLICATE_SAME_ACCESS. |
| 901 FALSE, | 958 FALSE, |
| 902 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 959 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
| 903 DLOG(ERROR) << "DuplicateHandle() failed"; | 960 DLOG(ERROR) << "DuplicateHandle() failed"; |
| 904 return false; | 961 return false; |
| 905 } | 962 } |
| 906 handles_for_renderer.push_back( | 963 handles_for_renderer.push_back( |
| 907 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); | 964 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); |
| 908 #else | 965 #else |
| 909 // No need to dup the imc_handle - we don't pass it anywhere else so | 966 // No need to dup the imc_handle - we don't pass it anywhere else so |
| 910 // it cannot be closed. | 967 // it cannot be closed. |
| 911 nacl::FileDescriptor imc_handle; | 968 nacl::FileDescriptor imc_handle; |
| 912 imc_handle.fd = internal_->sockets_for_renderer[i]; | 969 imc_handle.fd = internal_->sockets_for_renderer[i]; |
| 913 imc_handle.auto_close = true; | 970 imc_handle.auto_close = true; |
| 914 handles_for_renderer.push_back(imc_handle); | 971 handles_for_renderer.push_back(imc_handle); |
| 915 #endif | 972 #endif |
| 916 } | 973 } |
| 917 | 974 |
| 918 const ChildProcessData& data = process_->GetData(); | 975 const ChildProcessData& data = process_->GetData(); |
| 976 base::ProcessHandle nacl_process_handle; | |
| 919 #if defined(OS_WIN) | 977 #if defined(OS_WIN) |
| 920 // Copy the process handle into the renderer process. | 978 // Copy the process handle into the renderer process. |
| 921 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 979 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
| 922 data.handle, | 980 data.handle, |
| 923 chrome_render_message_filter_->peer_handle(), | 981 chrome_render_message_filter_->peer_handle(), |
| 924 &nacl_process_handle, | 982 &nacl_process_handle, |
| 925 PROCESS_DUP_HANDLE, | 983 PROCESS_DUP_HANDLE, |
| 926 FALSE, | 984 FALSE, |
| 927 0)) { | 985 0)) { |
| 928 DLOG(ERROR) << "DuplicateHandle() failed"; | 986 DLOG(ERROR) << "DuplicateHandle() failed"; |
| 929 return false; | 987 return false; |
| 930 } | 988 } |
| 931 #else | 989 #else |
| 932 // We use pid as process handle on Posix | 990 // We use pid as process handle on Posix |
| 933 nacl_process_handle = data.handle; | 991 nacl_process_handle = data.handle; |
| 934 #endif | 992 #endif |
| 935 | 993 |
| 936 // Get the pid of the NaCl process | 994 // Get the pid of the NaCl process |
| 937 base::ProcessId nacl_process_id = base::GetProcId(data.handle); | 995 base::ProcessId nacl_process_id = base::GetProcId(data.handle); |
| 938 | 996 |
| 939 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( | 997 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( |
| 940 reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id); | 998 reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id); |
| 941 chrome_render_message_filter_->Send(reply_msg_); | 999 chrome_render_message_filter_->Send(reply_msg_); |
| 942 chrome_render_message_filter_ = NULL; | 1000 chrome_render_message_filter_ = NULL; |
| 943 reply_msg_ = NULL; | 1001 reply_msg_ = NULL; |
| 944 internal_->sockets_for_renderer.clear(); | 1002 internal_->sockets_for_renderer.clear(); |
| 1003 return true; | |
| 1004 } | |
| 945 | 1005 |
| 946 std::vector<nacl::FileDescriptor> handles_for_sel_ldr; | 1006 bool NaClProcessHost::SendStart() { |
| 947 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 1007 return ReplyToRenderer() && StartNaClExecution(); |
| 948 if (!SendHandleToSelLdr(data.handle, | |
| 949 internal_->sockets_for_sel_ldr[i], true, | |
| 950 &handles_for_sel_ldr)) { | |
| 951 return false; | |
| 952 } | |
| 953 } | |
| 954 | |
| 955 // Send over the IRT file handle. We don't close our own copy! | |
| 956 if (!SendHandleToSelLdr(data.handle, irt_file, false, &handles_for_sel_ldr)) | |
| 957 return false; | |
| 958 | |
| 959 #if defined(OS_MACOSX) | |
| 960 // For dynamic loading support, NaCl requires a file descriptor that | |
| 961 // was created in /tmp, since those created with shm_open() are not | |
| 962 // mappable with PROT_EXEC. Rather than requiring an extra IPC | |
| 963 // round trip out of the sandbox, we create an FD here. | |
| 964 base::SharedMemory memory_buffer; | |
| 965 base::SharedMemoryCreateOptions options; | |
| 966 options.size = 1; | |
| 967 options.executable = true; | |
| 968 if (!memory_buffer.Create(options)) { | |
| 969 DLOG(ERROR) << "Failed to allocate memory buffer"; | |
| 970 return false; | |
| 971 } | |
| 972 nacl::FileDescriptor memory_fd; | |
| 973 memory_fd.fd = dup(memory_buffer.handle().fd); | |
| 974 if (memory_fd.fd < 0) { | |
| 975 DLOG(ERROR) << "Failed to dup() a file descriptor"; | |
| 976 return false; | |
| 977 } | |
| 978 memory_fd.auto_close = true; | |
| 979 handles_for_sel_ldr.push_back(memory_fd); | |
| 980 #endif | |
| 981 | |
| 982 // Sending the version string over IPC avoids linkage issues in cases where | |
| 983 // NaCl is not compiled into the main Chromium executable or DLL. | |
| 984 chrome::VersionInfo version_info; | |
| 985 IPC::Message* start_message = | |
| 986 new NaClProcessMsg_Start(handles_for_sel_ldr, | |
| 987 nacl_browser->GetValidatorCacheKey(), | |
| 988 version_info.CreateVersionString(), | |
| 989 enable_exception_handling_); | |
| 990 #if defined(OS_WIN) | |
| 991 if (debug_context_ != NULL) { | |
| 992 debug_context_->SetStartMessage(start_message); | |
| 993 debug_context_->SendStartMessage(); | |
| 994 } else { | |
| 995 process_->Send(start_message); | |
| 996 } | |
| 997 #else | |
| 998 process_->Send(start_message); | |
| 999 #endif | |
| 1000 | |
| 1001 internal_->sockets_for_sel_ldr.clear(); | |
| 1002 return true; | |
| 1003 } | 1008 } |
| 1004 | 1009 |
| 1005 bool NaClProcessHost::StartWithLaunchedProcess() { | 1010 bool NaClProcessHost::StartWithLaunchedProcess() { |
| 1006 #if defined(OS_LINUX) | 1011 #if defined(OS_LINUX) |
| 1007 if (wait_for_nacl_gdb_) { | 1012 if (wait_for_nacl_gdb_) { |
| 1008 if (LaunchNaClGdb(base::GetProcId(process_->GetData().handle))) { | 1013 if (LaunchNaClGdb(base::GetProcId(process_->GetData().handle))) { |
| 1009 // We will be called with wait_for_nacl_gdb_ = false once debugger is | 1014 // We will be called with wait_for_nacl_gdb_ = false once debugger is |
| 1010 // attached to the program. | 1015 // attached to the program. |
| 1011 return true; | 1016 return true; |
| 1012 } | 1017 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1025 } | 1030 } |
| 1026 | 1031 |
| 1027 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, | 1032 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, |
| 1028 bool* result) { | 1033 bool* result) { |
| 1029 *result = NaClBrowser::GetInstance()->QueryKnownToValidate(signature); | 1034 *result = NaClBrowser::GetInstance()->QueryKnownToValidate(signature); |
| 1030 } | 1035 } |
| 1031 | 1036 |
| 1032 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { | 1037 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { |
| 1033 NaClBrowser::GetInstance()->SetKnownToValidate(signature); | 1038 NaClBrowser::GetInstance()->SetKnownToValidate(signature); |
| 1034 } | 1039 } |
| OLD | NEW |