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 "components/nacl/browser/nacl_process_host.h" | 5 #include "components/nacl/browser/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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 | 187 |
| 188 void SetCloseOnExec(NaClHandle fd) { | 188 void SetCloseOnExec(NaClHandle fd) { |
| 189 #if defined(OS_POSIX) | 189 #if defined(OS_POSIX) |
| 190 int flags = fcntl(fd, F_GETFD); | 190 int flags = fcntl(fd, F_GETFD); |
| 191 CHECK_NE(flags, -1); | 191 CHECK_NE(flags, -1); |
| 192 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); | 192 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| 193 CHECK_EQ(rc, 0); | 193 CHECK_EQ(rc, 0); |
| 194 #endif | 194 #endif |
| 195 } | 195 } |
| 196 | 196 |
| 197 bool ShareHandleToSelLdr( | |
| 198 base::ProcessHandle processh, | |
| 199 NaClHandle sourceh, | |
| 200 bool close_source, | |
| 201 std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { | |
| 202 #if defined(OS_WIN) | |
| 203 HANDLE channel; | |
| 204 int flags = DUPLICATE_SAME_ACCESS; | |
| 205 if (close_source) | |
| 206 flags |= DUPLICATE_CLOSE_SOURCE; | |
| 207 if (!DuplicateHandle(GetCurrentProcess(), | |
| 208 reinterpret_cast<HANDLE>(sourceh), | |
| 209 processh, | |
| 210 &channel, | |
| 211 0, // Unused given DUPLICATE_SAME_ACCESS. | |
| 212 FALSE, | |
| 213 flags)) { | |
| 214 LOG(ERROR) << "DuplicateHandle() failed"; | |
| 215 return false; | |
| 216 } | |
| 217 handles_for_sel_ldr->push_back( | |
| 218 reinterpret_cast<nacl::FileDescriptor>(channel)); | |
| 219 #else | |
| 220 nacl::FileDescriptor channel; | |
| 221 channel.fd = sourceh; | |
| 222 channel.auto_close = close_source; | |
| 223 handles_for_sel_ldr->push_back(channel); | |
| 224 #endif | |
| 225 return true; | |
| 226 } | |
| 227 | |
| 228 void CloseFile(base::File file) { | 197 void CloseFile(base::File file) { |
| 229 // The base::File destructor will close the file for us. | 198 // The base::File destructor will close the file for us. |
| 230 } | 199 } |
| 231 | 200 |
| 232 } // namespace | 201 } // namespace |
| 233 | 202 |
| 234 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 203 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
| 235 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 204 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
| 236 | 205 |
| 237 NaClProcessHost::NaClProcessHost( | 206 NaClProcessHost::NaClProcessHost( |
| 238 const GURL& manifest_url, | 207 const GURL& manifest_url, |
| 239 base::File nexe_file, | 208 base::File nexe_file, |
| 240 const NaClFileToken& nexe_token, | 209 const NaClFileToken& nexe_token, |
| 241 const std::vector< | 210 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, |
| 242 nacl::NaClResourceFileInfo>& prefetched_resource_files_info, | |
| 243 ppapi::PpapiPermissions permissions, | 211 ppapi::PpapiPermissions permissions, |
| 244 int render_view_id, | 212 int render_view_id, |
| 245 uint32 permission_bits, | 213 uint32 permission_bits, |
| 246 bool uses_nonsfi_mode, | 214 bool uses_nonsfi_mode, |
| 247 bool off_the_record, | 215 bool off_the_record, |
| 248 NaClAppProcessType process_type, | 216 NaClAppProcessType process_type, |
| 249 const base::FilePath& profile_directory) | 217 const base::FilePath& profile_directory) |
| 250 : manifest_url_(manifest_url), | 218 : manifest_url_(manifest_url), |
| 251 nexe_file_(nexe_file.Pass()), | 219 nexe_file_(nexe_file.Pass()), |
| 252 nexe_token_(nexe_token), | 220 nexe_token_(nexe_token), |
| 253 prefetched_resource_files_info_(prefetched_resource_files_info), | 221 prefetched_resource_files_(prefetched_resource_files), |
| 254 permissions_(permissions), | 222 permissions_(permissions), |
| 255 #if defined(OS_WIN) | 223 #if defined(OS_WIN) |
| 256 process_launched_by_broker_(false), | 224 process_launched_by_broker_(false), |
| 257 #endif | 225 #endif |
| 258 reply_msg_(NULL), | 226 reply_msg_(NULL), |
| 259 #if defined(OS_WIN) | 227 #if defined(OS_WIN) |
| 260 debug_exception_handler_requested_(false), | 228 debug_exception_handler_requested_(false), |
| 261 #endif | 229 #endif |
| 262 uses_nonsfi_mode_(uses_nonsfi_mode), | 230 uses_nonsfi_mode_(uses_nonsfi_mode), |
| 263 enable_debug_stub_(false), | 231 enable_debug_stub_(false), |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 291 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 259 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
| 292 exit_code, exit_code); | 260 exit_code, exit_code); |
| 293 if (exit_code == 0) { | 261 if (exit_code == 0) { |
| 294 VLOG(1) << message; | 262 VLOG(1) << message; |
| 295 } else { | 263 } else { |
| 296 LOG(ERROR) << message; | 264 LOG(ERROR) << message; |
| 297 } | 265 } |
| 298 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); | 266 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); |
| 299 } | 267 } |
| 300 | 268 |
| 301 for (size_t i = 0; i < prefetched_resource_files_info_.size(); ++i) { | 269 // Note: this does not work on Windows, though we currently support this |
|
Mark Seaborn
2015/04/24 00:53:24
"this feature" -> "this prefetching feature"
hidehiko
2015/04/24 10:05:17
Done.
| |
| 270 // feature only on Non-SFI mode, which is supported only on Linux/ChromeOS, | |
| 271 // so it should be ok. | |
|
Mark Seaborn
2015/04/24 00:53:24
I'm not sure what you mean by "it should be ok".
hidehiko
2015/04/24 10:05:17
Done.
| |
| 272 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { | |
| 302 // The process failed to launch for some reason. Close resource file | 273 // The process failed to launch for some reason. Close resource file |
| 303 // handles. | 274 // handles. |
| 304 base::File file(IPC::PlatformFileForTransitToFile( | 275 base::File file(IPC::PlatformFileForTransitToFile( |
| 305 prefetched_resource_files_info_[i].file)); | 276 prefetched_resource_files_[i].file)); |
| 306 content::BrowserThread::GetBlockingPool()->PostTask( | 277 content::BrowserThread::GetBlockingPool()->PostTask( |
| 307 FROM_HERE, | 278 FROM_HERE, |
| 308 base::Bind(&CloseFile, base::Passed(file.Pass()))); | 279 base::Bind(&CloseFile, base::Passed(file.Pass()))); |
| 309 } | 280 } |
| 310 | 281 |
| 311 if (reply_msg_) { | 282 if (reply_msg_) { |
| 312 // The process failed to launch for some reason. | 283 // The process failed to launch for some reason. |
| 313 // Don't keep the renderer hanging. | 284 // Don't keep the renderer hanging. |
| 314 reply_msg_->set_reply_error(); | 285 reply_msg_->set_reply_error(); |
| 315 nacl_host_message_filter_->Send(reply_msg_); | 286 nacl_host_message_filter_->Send(reply_msg_); |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 } | 808 } |
| 838 } else { | 809 } else { |
| 839 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 810 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
| 840 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 811 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
| 841 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 812 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
| 842 params.enable_debug_stub = enable_nacl_debug; | 813 params.enable_debug_stub = enable_nacl_debug; |
| 843 params.enable_mojo = base::CommandLine::ForCurrentProcess()->HasSwitch( | 814 params.enable_mojo = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 844 switches::kEnableNaClMojo); | 815 switches::kEnableNaClMojo); |
| 845 | 816 |
| 846 const ChildProcessData& data = process_->GetData(); | 817 const ChildProcessData& data = process_->GetData(); |
| 847 if (!ShareHandleToSelLdr(data.handle, | 818 params.imc_bootstrap_handle = |
| 848 socket_for_sel_ldr_.TakePlatformFile(), | 819 IPC::TakeFileHandleForProcess(socket_for_sel_ldr_.Pass(), data.handle); |
| 849 true, | 820 if (params.imc_bootstrap_handle == IPC::InvalidPlatformFileForTransit()) { |
| 850 ¶ms.handles)) { | |
| 851 return false; | 821 return false; |
| 852 } | 822 } |
| 853 | 823 |
| 854 const base::File& irt_file = nacl_browser->IrtFile(); | 824 const base::File& irt_file = nacl_browser->IrtFile(); |
| 855 CHECK(irt_file.IsValid()); | 825 CHECK(irt_file.IsValid()); |
| 856 // Send over the IRT file handle. We don't close our own copy! | 826 // Send over the IRT file handle. We don't close our own copy! |
| 857 if (!ShareHandleToSelLdr(data.handle, irt_file.GetPlatformFile(), false, | 827 params.irt_handle = IPC::GetFileHandleForProcess( |
| 858 ¶ms.handles)) { | 828 irt_file.GetPlatformFile(), data.handle, false); |
| 829 if (params.irt_handle == IPC::InvalidPlatformFileForTransit()) { | |
| 859 return false; | 830 return false; |
| 860 } | 831 } |
| 861 | 832 |
| 862 #if defined(OS_MACOSX) | 833 #if defined(OS_MACOSX) |
| 863 // For dynamic loading support, NaCl requires a file descriptor that | 834 // For dynamic loading support, NaCl requires a file descriptor that |
| 864 // was created in /tmp, since those created with shm_open() are not | 835 // was created in /tmp, since those created with shm_open() are not |
| 865 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 836 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
| 866 // round trip out of the sandbox, we create an FD here. | 837 // round trip out of the sandbox, we create an FD here. |
| 867 base::SharedMemory memory_buffer; | 838 base::SharedMemory memory_buffer; |
| 868 base::SharedMemoryCreateOptions options; | 839 base::SharedMemoryCreateOptions options; |
| 869 options.size = 1; | 840 options.size = 1; |
| 870 options.executable = true; | 841 options.executable = true; |
| 871 if (!memory_buffer.Create(options)) { | 842 if (!memory_buffer.Create(options)) { |
| 872 DLOG(ERROR) << "Failed to allocate memory buffer"; | 843 DLOG(ERROR) << "Failed to allocate memory buffer"; |
| 873 return false; | 844 return false; |
| 874 } | 845 } |
| 875 FileDescriptor memory_fd; | 846 base::ScopedFD memory_fd(dup(memory_buffer.handle().fd)); |
| 876 memory_fd.fd = dup(memory_buffer.handle().fd); | 847 if (!memory_fd.is_valid()) { |
| 877 if (memory_fd.fd < 0) { | |
| 878 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 848 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
| 879 return false; | 849 return false; |
| 880 } | 850 } |
| 881 memory_fd.auto_close = true; | 851 params.mac_shm_fd = IPC::GetFileHandleForProcess( |
| 882 params.handles.push_back(memory_fd); | 852 memory_fd.release(), data.handle, true); |
| 883 #endif | 853 #endif |
| 884 | 854 |
| 885 #if defined(OS_POSIX) | 855 #if defined(OS_POSIX) |
| 886 if (params.enable_debug_stub) { | 856 if (params.enable_debug_stub) { |
| 887 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 857 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); |
| 888 if (server_bound_socket != net::kInvalidSocket) { | 858 if (server_bound_socket != net::kInvalidSocket) { |
| 889 params.debug_stub_server_bound_socket = | 859 params.debug_stub_server_bound_socket = IPC::GetFileHandleForProcess( |
| 890 FileDescriptor(server_bound_socket, true); | 860 server_bound_socket, data.handle, true); |
| 891 } | 861 } |
| 892 } | 862 } |
| 893 #endif | 863 #endif |
| 894 } | 864 } |
| 895 | 865 |
| 896 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, | 866 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, |
| 897 ¶ms.crash_info_shmem_handle)) { | 867 ¶ms.crash_info_shmem_handle)) { |
| 898 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; | 868 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; |
| 899 return false; | 869 return false; |
| 900 } | 870 } |
| 901 | 871 |
| 902 base::FilePath file_path; | 872 base::FilePath file_path; |
| 903 if (uses_nonsfi_mode_) { | 873 if (uses_nonsfi_mode_) { |
| 904 // Don't retrieve the file path when using nonsfi mode; there's no | 874 // Don't retrieve the file path when using nonsfi mode; there's no |
| 905 // validation caching in that case, so it's unnecessary work, and would | 875 // validation caching in that case, so it's unnecessary work, and would |
| 906 // expose the file path to the plugin. | 876 // expose the file path to the plugin. |
| 907 | 877 |
| 908 // Pass the pre-opened resource files to the loader. For the same reason | 878 // Pass the pre-opened resource files to the loader. For the same reason |
| 909 // as above, use an empty base::FilePath. | 879 // as above, use an empty base::FilePath. |
| 910 for (size_t i = 0; i < prefetched_resource_files_info_.size(); ++i) { | 880 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { |
| 911 params.prefetched_resource_files.push_back( | 881 params.prefetched_resource_files.push_back(NaClResourcePrefetchResult( |
| 912 NaClResourceFileInfo(prefetched_resource_files_info_[i].file, | 882 prefetched_resource_files_[i].file, |
| 913 base::FilePath(), | 883 base::FilePath(), |
| 914 prefetched_resource_files_info_[i].file_key)); | 884 prefetched_resource_files_[i].file_key)); |
| 915 } | 885 } |
| 916 prefetched_resource_files_info_.clear(); | 886 prefetched_resource_files_.clear(); |
| 917 } else { | 887 } else { |
| 918 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, | 888 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, |
| 919 nexe_token_.hi, | 889 nexe_token_.hi, |
| 920 &file_path)) { | 890 &file_path)) { |
| 921 // We have to reopen the file in the browser process; we don't want a | 891 // We have to reopen the file in the browser process; we don't want a |
| 922 // compromised renderer to pass an arbitrary fd that could get loaded | 892 // compromised renderer to pass an arbitrary fd that could get loaded |
| 923 // into the plugin process. | 893 // into the plugin process. |
| 924 if (base::PostTaskAndReplyWithResult( | 894 if (base::PostTaskAndReplyWithResult( |
| 925 content::BrowserThread::GetBlockingPool(), | 895 content::BrowserThread::GetBlockingPool(), |
| 926 FROM_HERE, | 896 FROM_HERE, |
| 927 base::Bind(OpenNaClReadExecImpl, | 897 base::Bind(OpenNaClReadExecImpl, |
| 928 file_path, | 898 file_path, |
| 929 true /* is_executable */), | 899 true /* is_executable */), |
| 930 base::Bind(&NaClProcessHost::StartNaClFileResolved, | 900 base::Bind(&NaClProcessHost::StartNaClFileResolved, |
| 931 weak_factory_.GetWeakPtr(), | 901 weak_factory_.GetWeakPtr(), |
| 932 params, | 902 params, |
| 933 file_path))) { | 903 file_path))) { |
| 934 return true; | 904 return true; |
| 935 } | 905 } |
| 936 } | 906 } |
| 937 // TODO(yusukes): Handle |prefetched_resource_files_info_| for SFI-NaCl. | 907 // TODO(yusukes): Handle |prefetched_resource_files_| for SFI-NaCl. |
| 938 DCHECK(prefetched_resource_files_info_.empty()); | 908 DCHECK(prefetched_resource_files_.empty()); |
| 939 } | 909 } |
| 940 | 910 |
| 941 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | 911 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), |
| 942 process_->GetData().handle); | 912 process_->GetData().handle); |
| 943 process_->Send(new NaClProcessMsg_Start(params)); | 913 process_->Send(new NaClProcessMsg_Start(params)); |
| 944 return true; | 914 return true; |
| 945 } | 915 } |
| 946 | 916 |
| 947 void NaClProcessHost::StartNaClFileResolved( | 917 void NaClProcessHost::StartNaClFileResolved( |
| 948 NaClStartParams params, | 918 NaClStartParams params, |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1208 process.Pass(), info, | 1178 process.Pass(), info, |
| 1209 base::MessageLoopProxy::current(), | 1179 base::MessageLoopProxy::current(), |
| 1210 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1180 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
| 1211 weak_factory_.GetWeakPtr())); | 1181 weak_factory_.GetWeakPtr())); |
| 1212 return true; | 1182 return true; |
| 1213 } | 1183 } |
| 1214 } | 1184 } |
| 1215 #endif | 1185 #endif |
| 1216 | 1186 |
| 1217 } // namespace nacl | 1187 } // namespace nacl |
| OLD | NEW |