| 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 |
| 11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
| 15 #include "base/macros.h" |
| 15 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 17 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 18 #include "base/process/launch.h" | 19 #include "base/process/launch.h" |
| 19 #include "base/process/process_iterator.h" | 20 #include "base/process/process_iterator.h" |
| 20 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 21 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 22 #include "base/strings/string_split.h" | 23 #include "base/strings/string_split.h" |
| 23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 24 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 188 |
| 188 void SetCloseOnExec(NaClHandle fd) { | 189 void SetCloseOnExec(NaClHandle fd) { |
| 189 #if defined(OS_POSIX) | 190 #if defined(OS_POSIX) |
| 190 int flags = fcntl(fd, F_GETFD); | 191 int flags = fcntl(fd, F_GETFD); |
| 191 CHECK_NE(flags, -1); | 192 CHECK_NE(flags, -1); |
| 192 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); | 193 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| 193 CHECK_EQ(rc, 0); | 194 CHECK_EQ(rc, 0); |
| 194 #endif | 195 #endif |
| 195 } | 196 } |
| 196 | 197 |
| 197 bool ShareHandleToSelLdr( | 198 // The maximum number of resource file handles NaClProcessMsg_Start message |
| 198 base::ProcessHandle processh, | 199 // can have. Currently IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage |
| 199 NaClHandle sourceh, | 200 // is 128 and NaCl sends 5 handles for other purposes, hence 123. |
| 200 bool close_source, | 201 const size_t kMaxPreOpenResourceFiles = 123; |
| 201 std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { | 202 |
| 202 #if defined(OS_WIN) | 203 #if defined(OS_POSIX) |
| 203 HANDLE channel; | 204 static_assert(kMaxPreOpenResourceFiles == |
| 204 int flags = DUPLICATE_SAME_ACCESS; | 205 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage - 5, |
| 205 if (close_source) | 206 "kMaxPreOpenResourceFiles is not up to date"); |
| 206 flags |= DUPLICATE_CLOSE_SOURCE; | 207 #endif |
| 207 if (!DuplicateHandle(GetCurrentProcess(), | 208 |
| 208 reinterpret_cast<HANDLE>(sourceh), | 209 void BatchOpenResourceFiles( |
| 209 processh, | 210 const std::vector<NaClResourcePrefetchInfo>& resource_prefetch_info_list, |
| 210 &channel, | 211 const base::FilePath& profile_directory, |
| 211 0, // Unused given DUPLICATE_SAME_ACCESS. | 212 base::ProcessHandle target_process, |
| 212 FALSE, | 213 std::vector<NaClResourceFileInfo>* prefetched_resource_files) { |
| 213 flags)) { | 214 // If output buffer is null, which means there is no resource info to be |
| 214 LOG(ERROR) << "DuplicateHandle() failed"; | 215 // opened, do nothing. |
| 215 return false; | 216 if (!prefetched_resource_files) { |
| 217 DCHECK(resource_prefetch_info_list.empty()); |
| 218 return; |
| 216 } | 219 } |
| 217 handles_for_sel_ldr->push_back( | 220 |
| 218 reinterpret_cast<nacl::FileDescriptor>(channel)); | 221 NaClBrowserDelegate* browser_delegate = NaClBrowser::GetDelegate(); |
| 219 #else | 222 for (size_t i = 0; |
| 220 nacl::FileDescriptor channel; | 223 i < resource_prefetch_info_list.size() && |
| 221 channel.fd = sourceh; | 224 prefetched_resource_files->size() < kMaxPreOpenResourceFiles; |
| 222 channel.auto_close = close_source; | 225 ++i) { |
| 223 handles_for_sel_ldr->push_back(channel); | 226 base::FilePath filepath; |
| 224 #endif | 227 if (!browser_delegate->MapUrlToLocalFilePath( |
| 225 return true; | 228 GURL(resource_prefetch_info_list[i].resource_url), |
| 229 true, // use blocking api. |
| 230 profile_directory, |
| 231 &filepath)) { |
| 232 continue; |
| 233 } |
| 234 |
| 235 base::File file = nacl::OpenNaClReadExecImpl( |
| 236 filepath, true /* executable */); |
| 237 if (!file.IsValid()) |
| 238 continue; |
| 239 |
| 240 // Note: this runs only in Non-SFI mode. So, do not pass the file path; |
| 241 // there's no validation caching in that case, so it's unnecessary, moreover |
| 242 // it would expose the file path to the plugin. |
| 243 prefetched_resource_files->push_back(NaClResourceFileInfo( |
| 244 IPC::TakeFileHandleForProcess(file.Pass(), target_process), |
| 245 base::FilePath(), |
| 246 resource_prefetch_info_list[i].manifest_key)); |
| 247 } |
| 226 } | 248 } |
| 227 | 249 |
| 228 void CloseFile(base::File file) { | 250 base::File ReopenNexeFile( |
| 229 // The base::File destructor will close the file for us. | 251 base::File nexe_file, base::FilePath* nexe_file_path) { |
| 252 // If no path is specified, use the original |nexe_file|. |
| 253 if (!nexe_file_path || nexe_file_path->empty()) |
| 254 return nexe_file.Pass(); |
| 255 |
| 256 // Reopen the nexe file. |
| 257 base::File reopened_file = nacl::OpenNaClReadExecImpl( |
| 258 *nexe_file_path, true /* executable */); |
| 259 if (!reopened_file.IsValid()) { |
| 260 // On fail, clear the path, which will eventually passed to the loader. |
| 261 nexe_file_path->clear(); |
| 262 return nexe_file.Pass(); |
| 263 } |
| 264 |
| 265 // Note that, the original |nexe_file| will be closed automatically. |
| 266 return reopened_file.Pass(); |
| 267 } |
| 268 |
| 269 // StartNaClExecution needs file operations. This function takes it, and should |
| 270 // run on blocking pool. |
| 271 base::File ResolveNaClFile( |
| 272 base::FilePath* nexe_file_path, |
| 273 base::File nexe_file, |
| 274 const std::vector<NaClResourcePrefetchInfo>& resource_prefetch_info_list, |
| 275 const base::FilePath& profile_directory, |
| 276 base::ProcessHandle target_process, |
| 277 std::vector<NaClResourceFileInfo>* prefetched_resource_files) { |
| 278 BatchOpenResourceFiles(resource_prefetch_info_list, |
| 279 profile_directory, |
| 280 target_process, |
| 281 prefetched_resource_files); |
| 282 return ReopenNexeFile(nexe_file.Pass(), nexe_file_path); |
| 230 } | 283 } |
| 231 | 284 |
| 232 } // namespace | 285 } // namespace |
| 233 | 286 |
| 234 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 287 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
| 235 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 288 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
| 236 | 289 |
| 237 NaClProcessHost::NaClProcessHost( | 290 NaClProcessHost::NaClProcessHost( |
| 238 const GURL& manifest_url, | 291 const GURL& manifest_url, |
| 239 base::File nexe_file, | 292 base::File nexe_file, |
| 240 const NaClFileToken& nexe_token, | 293 const NaClFileToken& nexe_token, |
| 241 const std::vector< | 294 const std::vector<NaClResourcePrefetchInfo>& resource_prefetch_info_list, |
| 242 nacl::NaClResourceFileInfo>& prefetched_resource_files_info, | |
| 243 ppapi::PpapiPermissions permissions, | 295 ppapi::PpapiPermissions permissions, |
| 244 int render_view_id, | 296 int render_view_id, |
| 245 uint32 permission_bits, | 297 uint32 permission_bits, |
| 246 bool uses_nonsfi_mode, | 298 bool uses_nonsfi_mode, |
| 247 bool off_the_record, | 299 bool off_the_record, |
| 248 NaClAppProcessType process_type, | 300 NaClAppProcessType process_type, |
| 249 const base::FilePath& profile_directory) | 301 const base::FilePath& profile_directory) |
| 250 : manifest_url_(manifest_url), | 302 : manifest_url_(manifest_url), |
| 251 nexe_file_(nexe_file.Pass()), | 303 nexe_file_(nexe_file.Pass()), |
| 252 nexe_token_(nexe_token), | 304 nexe_token_(nexe_token), |
| 253 prefetched_resource_files_info_(prefetched_resource_files_info), | 305 resource_prefetch_info_list_(resource_prefetch_info_list), |
| 254 permissions_(permissions), | 306 permissions_(permissions), |
| 255 #if defined(OS_WIN) | 307 #if defined(OS_WIN) |
| 256 process_launched_by_broker_(false), | 308 process_launched_by_broker_(false), |
| 257 #endif | 309 #endif |
| 258 reply_msg_(NULL), | 310 reply_msg_(NULL), |
| 259 #if defined(OS_WIN) | 311 #if defined(OS_WIN) |
| 260 debug_exception_handler_requested_(false), | 312 debug_exception_handler_requested_(false), |
| 261 #endif | 313 #endif |
| 262 uses_nonsfi_mode_(uses_nonsfi_mode), | 314 uses_nonsfi_mode_(uses_nonsfi_mode), |
| 263 enable_debug_stub_(false), | 315 enable_debug_stub_(false), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 276 // for this use case. | 328 // for this use case. |
| 277 process_->SetName(net::FormatUrl(manifest_url_, std::string())); | 329 process_->SetName(net::FormatUrl(manifest_url_, std::string())); |
| 278 | 330 |
| 279 enable_debug_stub_ = base::CommandLine::ForCurrentProcess()->HasSwitch( | 331 enable_debug_stub_ = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 280 switches::kEnableNaClDebug); | 332 switches::kEnableNaClDebug); |
| 281 DCHECK(process_type_ != kUnknownNaClProcessType); | 333 DCHECK(process_type_ != kUnknownNaClProcessType); |
| 282 enable_crash_throttling_ = process_type_ != kNativeNaClProcessType; | 334 enable_crash_throttling_ = process_type_ != kNativeNaClProcessType; |
| 283 } | 335 } |
| 284 | 336 |
| 285 NaClProcessHost::~NaClProcessHost() { | 337 NaClProcessHost::~NaClProcessHost() { |
| 338 // Release the file received from the renderer. This has to be done on a |
| 339 // thread where IO is permitted, though. |
| 340 content::BrowserThread::GetBlockingPool()->PostTask( |
| 341 FROM_HERE, |
| 342 base::Bind(&ignore_result<base::File>, base::Passed(nexe_file_.Pass()))); |
| 343 |
| 286 // Report exit status only if the process was successfully started. | 344 // Report exit status only if the process was successfully started. |
| 287 if (process_->GetData().handle != base::kNullProcessHandle) { | 345 if (process_->GetData().handle != base::kNullProcessHandle) { |
| 288 int exit_code = 0; | 346 int exit_code = 0; |
| 289 process_->GetTerminationStatus(false /* known_dead */, &exit_code); | 347 process_->GetTerminationStatus(false /* known_dead */, &exit_code); |
| 290 std::string message = | 348 std::string message = |
| 291 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 349 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
| 292 exit_code, exit_code); | 350 exit_code, exit_code); |
| 293 if (exit_code == 0) { | 351 if (exit_code == 0) { |
| 294 VLOG(1) << message; | 352 VLOG(1) << message; |
| 295 } else { | 353 } else { |
| 296 LOG(ERROR) << message; | 354 LOG(ERROR) << message; |
| 297 } | 355 } |
| 298 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); | 356 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); |
| 299 } | 357 } |
| 300 | 358 |
| 301 for (size_t i = 0; i < prefetched_resource_files_info_.size(); ++i) { | |
| 302 // The process failed to launch for some reason. Close resource file | |
| 303 // handles. | |
| 304 base::File file(IPC::PlatformFileForTransitToFile( | |
| 305 prefetched_resource_files_info_[i].file)); | |
| 306 content::BrowserThread::GetBlockingPool()->PostTask( | |
| 307 FROM_HERE, | |
| 308 base::Bind(&CloseFile, base::Passed(file.Pass()))); | |
| 309 } | |
| 310 | |
| 311 if (reply_msg_) { | 359 if (reply_msg_) { |
| 312 // The process failed to launch for some reason. | 360 // The process failed to launch for some reason. |
| 313 // Don't keep the renderer hanging. | 361 // Don't keep the renderer hanging. |
| 314 reply_msg_->set_reply_error(); | 362 reply_msg_->set_reply_error(); |
| 315 nacl_host_message_filter_->Send(reply_msg_); | 363 nacl_host_message_filter_->Send(reply_msg_); |
| 316 } | 364 } |
| 317 #if defined(OS_WIN) | 365 #if defined(OS_WIN) |
| 318 if (process_launched_by_broker_) { | 366 if (process_launched_by_broker_) { |
| 319 NaClBrokerService::GetInstance()->OnLoaderDied(); | 367 NaClBrokerService::GetInstance()->OnLoaderDied(); |
| 320 } | 368 } |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 bool NaClProcessHost::StartNaClExecution() { | 865 bool NaClProcessHost::StartNaClExecution() { |
| 818 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 866 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 819 | 867 |
| 820 NaClStartParams params; | 868 NaClStartParams params; |
| 821 | 869 |
| 822 // Enable PPAPI proxy channel creation only for renderer processes. | 870 // Enable PPAPI proxy channel creation only for renderer processes. |
| 823 params.enable_ipc_proxy = enable_ppapi_proxy(); | 871 params.enable_ipc_proxy = enable_ppapi_proxy(); |
| 824 params.process_type = process_type_; | 872 params.process_type = process_type_; |
| 825 bool enable_nacl_debug = enable_debug_stub_ && | 873 bool enable_nacl_debug = enable_debug_stub_ && |
| 826 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); | 874 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); |
| 875 |
| 876 #if defined(OS_MACOSX) |
| 877 base::ScopedFD memory_fd; |
| 878 #endif // defined(OS_MACOSX) |
| 879 #if defined(OS_POSIX) |
| 880 base::ScopedFD debug_stub_server_bound_socket; |
| 881 #endif // defined(OS_POSIX) |
| 882 |
| 827 if (uses_nonsfi_mode_) { | 883 if (uses_nonsfi_mode_) { |
| 828 // Currently, non-SFI mode is supported only on Linux. | 884 // Currently, non-SFI mode is supported only on Linux. |
| 829 #if defined(OS_LINUX) | 885 #if defined(OS_LINUX) |
| 830 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is | 886 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is |
| 831 // not created. | 887 // not created. |
| 832 DCHECK(!socket_for_sel_ldr_.IsValid()); | 888 DCHECK(!socket_for_sel_ldr_.IsValid()); |
| 833 #endif | 889 #endif |
| 834 if (enable_nacl_debug) { | 890 if (enable_nacl_debug) { |
| 835 base::ProcessId pid = base::GetProcId(process_->GetData().handle); | 891 base::ProcessId pid = base::GetProcId(process_->GetData().handle); |
| 836 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; | 892 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; |
| 837 } | 893 } |
| 838 } else { | 894 } else { |
| 839 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 895 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
| 840 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 896 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
| 841 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 897 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
| 842 params.enable_debug_stub = enable_nacl_debug; | 898 params.enable_debug_stub = enable_nacl_debug; |
| 843 params.enable_mojo = base::CommandLine::ForCurrentProcess()->HasSwitch( | 899 params.enable_mojo = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 844 switches::kEnableNaClMojo); | 900 switches::kEnableNaClMojo); |
| 845 | 901 |
| 846 const ChildProcessData& data = process_->GetData(); | |
| 847 if (!ShareHandleToSelLdr(data.handle, | |
| 848 socket_for_sel_ldr_.TakePlatformFile(), | |
| 849 true, | |
| 850 ¶ms.handles)) { | |
| 851 return false; | |
| 852 } | |
| 853 | |
| 854 const base::File& irt_file = nacl_browser->IrtFile(); | |
| 855 CHECK(irt_file.IsValid()); | |
| 856 // Send over the IRT file handle. We don't close our own copy! | |
| 857 if (!ShareHandleToSelLdr(data.handle, irt_file.GetPlatformFile(), false, | |
| 858 ¶ms.handles)) { | |
| 859 return false; | |
| 860 } | |
| 861 | |
| 862 #if defined(OS_MACOSX) | 902 #if defined(OS_MACOSX) |
| 863 // For dynamic loading support, NaCl requires a file descriptor that | 903 // For dynamic loading support, NaCl requires a file descriptor that |
| 864 // was created in /tmp, since those created with shm_open() are not | 904 // was created in /tmp, since those created with shm_open() are not |
| 865 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 905 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
| 866 // round trip out of the sandbox, we create an FD here. | 906 // round trip out of the sandbox, we create an FD here. |
| 867 base::SharedMemory memory_buffer; | 907 base::SharedMemory memory_buffer; |
| 868 base::SharedMemoryCreateOptions options; | 908 base::SharedMemoryCreateOptions options; |
| 869 options.size = 1; | 909 options.size = 1; |
| 870 options.executable = true; | 910 options.executable = true; |
| 871 if (!memory_buffer.Create(options)) { | 911 if (!memory_buffer.Create(options)) { |
| 872 DLOG(ERROR) << "Failed to allocate memory buffer"; | 912 DLOG(ERROR) << "Failed to allocate memory buffer"; |
| 873 return false; | 913 return false; |
| 874 } | 914 } |
| 875 FileDescriptor memory_fd; | 915 memory_fd.reset(dup(memory_buffer.handle().fd)); |
| 876 memory_fd.fd = dup(memory_buffer.handle().fd); | 916 if (!memory_fd.is_valid()) { |
| 877 if (memory_fd.fd < 0) { | |
| 878 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 917 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
| 879 return false; | 918 return false; |
| 880 } | 919 } |
| 881 memory_fd.auto_close = true; | |
| 882 params.handles.push_back(memory_fd); | |
| 883 #endif | 920 #endif |
| 884 | 921 |
| 885 #if defined(OS_POSIX) | 922 #if defined(OS_POSIX) |
| 886 if (params.enable_debug_stub) { | 923 if (params.enable_debug_stub) { |
| 887 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 924 debug_stub_server_bound_socket.reset(GetDebugStubSocketHandle()); |
| 888 if (server_bound_socket != net::kInvalidSocket) { | |
| 889 params.debug_stub_server_bound_socket = | |
| 890 FileDescriptor(server_bound_socket, true); | |
| 891 } | |
| 892 } | 925 } |
| 893 #endif | 926 #endif |
| 894 } | 927 } |
| 895 | 928 |
| 896 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, | 929 // Transfer resources to |params|. |
| 897 ¶ms.crash_info_shmem_handle)) { | 930 // Hereafter we should never return false, and should always send an IPC |
| 898 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; | 931 // to NaCl plugin process. Otherwise, the resources passed to |params| |
| 899 return false; | 932 // may be leaked. |
| 933 { |
| 934 const ChildProcessData& data = process_->GetData(); |
| 935 if (!uses_nonsfi_mode_) { |
| 936 params.imc_bootstrap_handle = IPC::TakeFileHandleForProcess( |
| 937 socket_for_sel_ldr_.Pass(), data.handle); |
| 938 |
| 939 const base::File& irt_file = nacl_browser->IrtFile(); |
| 940 CHECK(irt_file.IsValid()); |
| 941 // Send over the IRT file handle. We don't close our own copy! |
| 942 params.irt_handle = IPC::GetFileHandleForProcess( |
| 943 irt_file.GetPlatformFile(), data.handle, false); |
| 944 |
| 945 #if defined(OS_MACOSX) |
| 946 params.mac_shm_fd = IPC::GetFileHandleForProcess( |
| 947 memory_fd.release(), data.handle, true); |
| 948 #endif |
| 949 |
| 950 #if defined(OS_POSIX) |
| 951 params.debug_stub_server_bound_socket = IPC::GetFileHandleForProcess( |
| 952 debug_stub_server_bound_socket.release(), data.handle, true); |
| 953 #endif |
| 954 } |
| 955 |
| 956 if (!crash_info_shmem_.ShareToProcess(data.handle, |
| 957 ¶ms.crash_info_shmem_handle)) { |
| 958 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; |
| 959 // Do not return. |
| 960 } |
| 900 } | 961 } |
| 901 | 962 |
| 902 base::FilePath file_path; | 963 // We have to reopen the file in the browser process; we don't want a |
| 903 if (uses_nonsfi_mode_) { | 964 // compromised renderer to pass an arbitrary fd that could get loaded |
| 965 // into the plugin process. |
| 966 scoped_ptr<base::FilePath> nexe_file_path; |
| 967 if (!uses_nonsfi_mode_) { |
| 904 // Don't retrieve the file path when using nonsfi mode; there's no | 968 // 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 | 969 // validation caching in that case, so it's unnecessary work, and would |
| 906 // expose the file path to the plugin. | 970 // expose the file path to the plugin. |
| 907 | 971 nexe_file_path.reset(new base::FilePath); |
| 908 // Pass the pre-opened resource files to the loader. For the same reason | 972 if (!NaClBrowser::GetInstance()->GetFilePath( |
| 909 // as above, use an empty base::FilePath. | 973 nexe_token_.lo, nexe_token_.hi, nexe_file_path.get())) { |
| 910 for (size_t i = 0; i < prefetched_resource_files_info_.size(); ++i) { | 974 // Failed. Reset the pointer. |
| 911 params.prefetched_resource_files.push_back( | 975 nexe_file_path.reset(); |
| 912 NaClResourceFileInfo(prefetched_resource_files_info_[i].file, | |
| 913 base::FilePath(), | |
| 914 prefetched_resource_files_info_[i].file_key)); | |
| 915 } | 976 } |
| 916 prefetched_resource_files_info_.clear(); | |
| 917 } else { | |
| 918 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, | |
| 919 nexe_token_.hi, | |
| 920 &file_path)) { | |
| 921 // 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 | |
| 923 // into the plugin process. | |
| 924 if (base::PostTaskAndReplyWithResult( | |
| 925 content::BrowserThread::GetBlockingPool(), | |
| 926 FROM_HERE, | |
| 927 base::Bind(OpenNaClReadExecImpl, | |
| 928 file_path, | |
| 929 true /* is_executable */), | |
| 930 base::Bind(&NaClProcessHost::StartNaClFileResolved, | |
| 931 weak_factory_.GetWeakPtr(), | |
| 932 params, | |
| 933 file_path))) { | |
| 934 return true; | |
| 935 } | |
| 936 } | |
| 937 // TODO(yusukes): Handle |prefetched_resource_files_info_| for SFI-NaCl. | |
| 938 DCHECK(prefetched_resource_files_info_.empty()); | |
| 939 } | 977 } |
| 940 | 978 |
| 941 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | 979 // Pass the pre-opened resource files to the loader. |
| 942 process_->GetData().handle); | 980 scoped_ptr<std::vector<NaClResourceFileInfo> > resource_info_list; |
| 943 process_->Send(new NaClProcessMsg_Start(params)); | 981 if (!resource_prefetch_info_list_.empty()) { |
| 982 // TODO(yusukes): Handle |prefetched_resource_files_info_| for SFI-NaCl. |
| 983 DCHECK(uses_nonsfi_mode_); |
| 984 resource_info_list.reset(new std::vector<NaClResourceFileInfo>); |
| 985 } |
| 986 |
| 987 // If file operation is necessary, run it on a blocking pool, where file |
| 988 // operations are allowed. |
| 989 if (nexe_file_path.get() || resource_info_list.get()) { |
| 990 if (base::PostTaskAndReplyWithResult( |
| 991 content::BrowserThread::GetBlockingPool(), |
| 992 FROM_HERE, |
| 993 base::Bind(&ResolveNaClFile, |
| 994 nexe_file_path.get(), |
| 995 base::Passed(&nexe_file_), |
| 996 resource_prefetch_info_list_, |
| 997 profile_directory_, |
| 998 process_->GetData().handle, |
| 999 resource_info_list.get()), |
| 1000 base::Bind(&NaClProcessHost::StartNaClExecutionAfterFileResolved, |
| 1001 weak_factory_.GetWeakPtr(), |
| 1002 params, |
| 1003 base::Passed(&nexe_file_path), |
| 1004 base::Passed(&resource_info_list)))) { |
| 1005 return true; |
| 1006 } |
| 1007 } |
| 1008 |
| 1009 StartNaClExecutionAfterFileResolved( |
| 1010 params, |
| 1011 scoped_ptr<base::FilePath>(), |
| 1012 scoped_ptr<std::vector<NaClResourceFileInfo> >(), |
| 1013 nexe_file_.Pass()); |
| 944 return true; | 1014 return true; |
| 945 } | 1015 } |
| 946 | 1016 |
| 947 void NaClProcessHost::StartNaClFileResolved( | 1017 void NaClProcessHost::StartNaClExecutionAfterFileResolved( |
| 948 NaClStartParams params, | 1018 NaClStartParams params, |
| 949 const base::FilePath& file_path, | 1019 scoped_ptr<base::FilePath> nexe_file_path, |
| 950 base::File checked_nexe_file) { | 1020 scoped_ptr<std::vector<NaClResourceFileInfo> > prefetched_resource_files, |
| 951 if (checked_nexe_file.IsValid()) { | 1021 base::File nexe_file) { |
| 952 // Release the file received from the renderer. This has to be done on a | 1022 // Pass the nexe file and its path to params. |
| 953 // thread where IO is permitted, though. | 1023 params.nexe_file = IPC::TakeFileHandleForProcess( |
| 954 content::BrowserThread::GetBlockingPool()->PostTask( | 1024 nexe_file.Pass(), process_->GetData().handle); |
| 955 FROM_HERE, | 1025 if (nexe_file_path.get()) { |
| 956 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); | 1026 params.nexe_file_path_metadata = *nexe_file_path; |
| 957 params.nexe_file_path_metadata = file_path; | |
| 958 params.nexe_file = IPC::TakeFileHandleForProcess( | |
| 959 checked_nexe_file.Pass(), process_->GetData().handle); | |
| 960 } else { | |
| 961 params.nexe_file = IPC::TakeFileHandleForProcess( | |
| 962 nexe_file_.Pass(), process_->GetData().handle); | |
| 963 } | 1027 } |
| 1028 |
| 1029 // Pass prefetched resources to params. |
| 1030 if (prefetched_resource_files.get()) { |
| 1031 prefetched_resource_files->swap(params.prefetched_resource_files); |
| 1032 } |
| 1033 |
| 964 process_->Send(new NaClProcessMsg_Start(params)); | 1034 process_->Send(new NaClProcessMsg_Start(params)); |
| 965 } | 1035 } |
| 966 | 1036 |
| 967 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 1037 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is |
| 968 // received. | 1038 // received. |
| 969 void NaClProcessHost::OnPpapiChannelsCreated( | 1039 void NaClProcessHost::OnPpapiChannelsCreated( |
| 970 const IPC::ChannelHandle& browser_channel_handle, | 1040 const IPC::ChannelHandle& browser_channel_handle, |
| 971 const IPC::ChannelHandle& ppapi_renderer_channel_handle, | 1041 const IPC::ChannelHandle& ppapi_renderer_channel_handle, |
| 972 const IPC::ChannelHandle& trusted_renderer_channel_handle, | 1042 const IPC::ChannelHandle& trusted_renderer_channel_handle, |
| 973 const IPC::ChannelHandle& manifest_service_channel_handle) { | 1043 const IPC::ChannelHandle& manifest_service_channel_handle) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1208 process.Pass(), info, | 1278 process.Pass(), info, |
| 1209 base::MessageLoopProxy::current(), | 1279 base::MessageLoopProxy::current(), |
| 1210 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1280 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
| 1211 weak_factory_.GetWeakPtr())); | 1281 weak_factory_.GetWeakPtr())); |
| 1212 return true; | 1282 return true; |
| 1213 } | 1283 } |
| 1214 } | 1284 } |
| 1215 #endif | 1285 #endif |
| 1216 | 1286 |
| 1217 } // namespace nacl | 1287 } // namespace nacl |
| OLD | NEW |