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 |
| 270 // prefetching feature only on Non-SFI mode, which is supported only on | |
| 271 // Linux/ChromeOS, so it should be ok. | |
| 272 #if defined(OS_WIN) | |
| 273 CHECK(prefetched_resource_files_.empty()); | |
|
Mark Seaborn
2015/04/24 14:26:12
Please use DCHECK to avoid the risk that this give
hidehiko
2015/04/24 18:07:53
Oh, right. Done.
| |
| 274 #else | |
| 275 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { | |
| 302 // The process failed to launch for some reason. Close resource file | 276 // The process failed to launch for some reason. Close resource file |
| 303 // handles. | 277 // handles. |
| 304 base::File file(IPC::PlatformFileForTransitToFile( | 278 base::File file(IPC::PlatformFileForTransitToFile( |
| 305 prefetched_resource_files_info_[i].file)); | 279 prefetched_resource_files_[i].file)); |
| 306 content::BrowserThread::GetBlockingPool()->PostTask( | 280 content::BrowserThread::GetBlockingPool()->PostTask( |
| 307 FROM_HERE, | 281 FROM_HERE, |
| 308 base::Bind(&CloseFile, base::Passed(file.Pass()))); | 282 base::Bind(&CloseFile, base::Passed(file.Pass()))); |
| 309 } | 283 } |
| 284 #endif | |
| 310 | 285 |
| 311 if (reply_msg_) { | 286 if (reply_msg_) { |
| 312 // The process failed to launch for some reason. | 287 // The process failed to launch for some reason. |
| 313 // Don't keep the renderer hanging. | 288 // Don't keep the renderer hanging. |
| 314 reply_msg_->set_reply_error(); | 289 reply_msg_->set_reply_error(); |
| 315 nacl_host_message_filter_->Send(reply_msg_); | 290 nacl_host_message_filter_->Send(reply_msg_); |
| 316 } | 291 } |
| 317 #if defined(OS_WIN) | 292 #if defined(OS_WIN) |
| 318 if (process_launched_by_broker_) { | 293 if (process_launched_by_broker_) { |
| 319 NaClBrokerService::GetInstance()->OnLoaderDied(); | 294 NaClBrokerService::GetInstance()->OnLoaderDied(); |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 base::ProcessId pid = base::GetProcId(process_->GetData().handle); | 810 base::ProcessId pid = base::GetProcId(process_->GetData().handle); |
| 836 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; | 811 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; |
| 837 } | 812 } |
| 838 } else { | 813 } else { |
| 839 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 814 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
| 840 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 815 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
| 841 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 816 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
| 842 params.enable_debug_stub = enable_nacl_debug; | 817 params.enable_debug_stub = enable_nacl_debug; |
| 843 | 818 |
| 844 const ChildProcessData& data = process_->GetData(); | 819 const ChildProcessData& data = process_->GetData(); |
| 845 if (!ShareHandleToSelLdr(data.handle, | 820 params.imc_bootstrap_handle = |
| 846 socket_for_sel_ldr_.TakePlatformFile(), | 821 IPC::TakeFileHandleForProcess(socket_for_sel_ldr_.Pass(), data.handle); |
| 847 true, | 822 if (params.imc_bootstrap_handle == IPC::InvalidPlatformFileForTransit()) { |
| 848 ¶ms.handles)) { | |
| 849 return false; | 823 return false; |
| 850 } | 824 } |
| 851 | 825 |
| 852 const base::File& irt_file = nacl_browser->IrtFile(); | 826 const base::File& irt_file = nacl_browser->IrtFile(); |
| 853 CHECK(irt_file.IsValid()); | 827 CHECK(irt_file.IsValid()); |
| 854 // Send over the IRT file handle. We don't close our own copy! | 828 // Send over the IRT file handle. We don't close our own copy! |
| 855 if (!ShareHandleToSelLdr(data.handle, irt_file.GetPlatformFile(), false, | 829 params.irt_handle = IPC::GetFileHandleForProcess( |
| 856 ¶ms.handles)) { | 830 irt_file.GetPlatformFile(), data.handle, false); |
| 831 if (params.irt_handle == IPC::InvalidPlatformFileForTransit()) { | |
| 857 return false; | 832 return false; |
| 858 } | 833 } |
| 859 | 834 |
| 860 #if defined(OS_MACOSX) | 835 #if defined(OS_MACOSX) |
| 861 // For dynamic loading support, NaCl requires a file descriptor that | 836 // For dynamic loading support, NaCl requires a file descriptor that |
| 862 // was created in /tmp, since those created with shm_open() are not | 837 // was created in /tmp, since those created with shm_open() are not |
| 863 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 838 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
| 864 // round trip out of the sandbox, we create an FD here. | 839 // round trip out of the sandbox, we create an FD here. |
| 865 base::SharedMemory memory_buffer; | 840 base::SharedMemory memory_buffer; |
| 866 base::SharedMemoryCreateOptions options; | 841 base::SharedMemoryCreateOptions options; |
| 867 options.size = 1; | 842 options.size = 1; |
| 868 options.executable = true; | 843 options.executable = true; |
| 869 if (!memory_buffer.Create(options)) { | 844 if (!memory_buffer.Create(options)) { |
| 870 DLOG(ERROR) << "Failed to allocate memory buffer"; | 845 DLOG(ERROR) << "Failed to allocate memory buffer"; |
| 871 return false; | 846 return false; |
| 872 } | 847 } |
| 873 FileDescriptor memory_fd; | 848 base::ScopedFD memory_fd(dup(memory_buffer.handle().fd)); |
| 874 memory_fd.fd = dup(memory_buffer.handle().fd); | 849 if (!memory_fd.is_valid()) { |
| 875 if (memory_fd.fd < 0) { | |
| 876 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 850 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
| 877 return false; | 851 return false; |
| 878 } | 852 } |
| 879 memory_fd.auto_close = true; | 853 params.mac_shm_fd = IPC::GetFileHandleForProcess( |
| 880 params.handles.push_back(memory_fd); | 854 memory_fd.release(), data.handle, true); |
| 881 #endif | 855 #endif |
| 882 | 856 |
| 883 #if defined(OS_POSIX) | 857 #if defined(OS_POSIX) |
| 884 if (params.enable_debug_stub) { | 858 if (params.enable_debug_stub) { |
| 885 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 859 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); |
| 886 if (server_bound_socket != net::kInvalidSocket) { | 860 if (server_bound_socket != net::kInvalidSocket) { |
| 887 params.debug_stub_server_bound_socket = | 861 params.debug_stub_server_bound_socket = IPC::GetFileHandleForProcess( |
| 888 FileDescriptor(server_bound_socket, true); | 862 server_bound_socket, data.handle, true); |
| 889 } | 863 } |
| 890 } | 864 } |
| 891 #endif | 865 #endif |
| 892 } | 866 } |
| 893 | 867 |
| 894 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, | 868 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, |
| 895 ¶ms.crash_info_shmem_handle)) { | 869 ¶ms.crash_info_shmem_handle)) { |
| 896 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; | 870 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; |
| 897 return false; | 871 return false; |
| 898 } | 872 } |
| 899 | 873 |
| 900 base::FilePath file_path; | 874 base::FilePath file_path; |
| 901 if (uses_nonsfi_mode_) { | 875 if (uses_nonsfi_mode_) { |
| 902 // Don't retrieve the file path when using nonsfi mode; there's no | 876 // Don't retrieve the file path when using nonsfi mode; there's no |
| 903 // validation caching in that case, so it's unnecessary work, and would | 877 // validation caching in that case, so it's unnecessary work, and would |
| 904 // expose the file path to the plugin. | 878 // expose the file path to the plugin. |
| 905 | 879 |
| 906 // Pass the pre-opened resource files to the loader. For the same reason | 880 // Pass the pre-opened resource files to the loader. For the same reason |
| 907 // as above, use an empty base::FilePath. | 881 // as above, use an empty base::FilePath. |
| 908 for (size_t i = 0; i < prefetched_resource_files_info_.size(); ++i) { | 882 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { |
| 909 params.prefetched_resource_files.push_back( | 883 params.prefetched_resource_files.push_back(NaClResourcePrefetchResult( |
| 910 NaClResourceFileInfo(prefetched_resource_files_info_[i].file, | 884 prefetched_resource_files_[i].file, |
| 911 base::FilePath(), | 885 base::FilePath(), |
| 912 prefetched_resource_files_info_[i].file_key)); | 886 prefetched_resource_files_[i].file_key)); |
| 913 } | 887 } |
| 914 prefetched_resource_files_info_.clear(); | 888 prefetched_resource_files_.clear(); |
| 915 } else { | 889 } else { |
| 916 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, | 890 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, |
| 917 nexe_token_.hi, | 891 nexe_token_.hi, |
| 918 &file_path)) { | 892 &file_path)) { |
| 919 // We have to reopen the file in the browser process; we don't want a | 893 // We have to reopen the file in the browser process; we don't want a |
| 920 // compromised renderer to pass an arbitrary fd that could get loaded | 894 // compromised renderer to pass an arbitrary fd that could get loaded |
| 921 // into the plugin process. | 895 // into the plugin process. |
| 922 if (base::PostTaskAndReplyWithResult( | 896 if (base::PostTaskAndReplyWithResult( |
| 923 content::BrowserThread::GetBlockingPool(), | 897 content::BrowserThread::GetBlockingPool(), |
| 924 FROM_HERE, | 898 FROM_HERE, |
| 925 base::Bind(OpenNaClReadExecImpl, | 899 base::Bind(OpenNaClReadExecImpl, |
| 926 file_path, | 900 file_path, |
| 927 true /* is_executable */), | 901 true /* is_executable */), |
| 928 base::Bind(&NaClProcessHost::StartNaClFileResolved, | 902 base::Bind(&NaClProcessHost::StartNaClFileResolved, |
| 929 weak_factory_.GetWeakPtr(), | 903 weak_factory_.GetWeakPtr(), |
| 930 params, | 904 params, |
| 931 file_path))) { | 905 file_path))) { |
| 932 return true; | 906 return true; |
| 933 } | 907 } |
| 934 } | 908 } |
| 935 // TODO(yusukes): Handle |prefetched_resource_files_info_| for SFI-NaCl. | 909 // TODO(yusukes): Handle |prefetched_resource_files_| for SFI-NaCl. |
| 936 DCHECK(prefetched_resource_files_info_.empty()); | 910 DCHECK(prefetched_resource_files_.empty()); |
| 937 } | 911 } |
| 938 | 912 |
| 939 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | 913 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), |
| 940 process_->GetData().handle); | 914 process_->GetData().handle); |
| 941 process_->Send(new NaClProcessMsg_Start(params)); | 915 process_->Send(new NaClProcessMsg_Start(params)); |
| 942 return true; | 916 return true; |
| 943 } | 917 } |
| 944 | 918 |
| 945 void NaClProcessHost::StartNaClFileResolved( | 919 void NaClProcessHost::StartNaClFileResolved( |
| 946 NaClStartParams params, | 920 NaClStartParams params, |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1206 process.Pass(), info, | 1180 process.Pass(), info, |
| 1207 base::MessageLoopProxy::current(), | 1181 base::MessageLoopProxy::current(), |
| 1208 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1182 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
| 1209 weak_factory_.GetWeakPtr())); | 1183 weak_factory_.GetWeakPtr())); |
| 1210 return true; | 1184 return true; |
| 1211 } | 1185 } |
| 1212 } | 1186 } |
| 1213 #endif | 1187 #endif |
| 1214 | 1188 |
| 1215 } // namespace nacl | 1189 } // namespace nacl |
| OLD | NEW |