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 void CloseFile(base::File file) { | 197 void PostCloseFile(base::File file) { |
| 198 if (!file.IsValid()) { |
| 199 return; |
| 200 } |
| 201 |
198 // The base::File destructor will close the file for us. | 202 // The base::File destructor will close the file for us. |
| 203 content::BrowserThread::GetBlockingPool()->PostTask( |
| 204 FROM_HERE, |
| 205 base::Bind(&ignore_result<base::File>, base::Passed(&file))); |
| 206 } |
| 207 |
| 208 // The maximum number of resource file handles the browser process accepts. Use |
| 209 // 200 because ARC's nmf has ~128 resource files as of May 2015. This prevents |
| 210 // untrusted code filling the FD/handle table. |
| 211 const size_t kMaxPreOpenResourceFiles = 200; |
| 212 |
| 213 void BatchOpenResourceFiles( |
| 214 const std::vector<NaClResourcePrefetchRequest>& request_list, |
| 215 const base::FilePath& profile_directory, |
| 216 base::ProcessHandle target_process, |
| 217 bool uses_nonsfi_mode, |
| 218 std::vector<NaClResourcePrefetchResult>* result_list) { |
| 219 if (!result_list) { |
| 220 // If output buffer is null, it means there is no resource to be opened. |
| 221 // Do nothing, then. |
| 222 DCHECK(request_list.empty()); |
| 223 return; |
| 224 } |
| 225 |
| 226 NaClBrowserDelegate* browser_delegate = NaClBrowser::GetDelegate(); |
| 227 for (size_t i = 0; |
| 228 i < request_list.size() && |
| 229 result_list->size() < kMaxPreOpenResourceFiles; |
| 230 ++i) { |
| 231 base::FilePath file_path; |
| 232 if (!browser_delegate->MapUrlToLocalFilePath( |
| 233 GURL(request_list[i].resource_url), |
| 234 true, // Use blocking API. |
| 235 profile_directory, |
| 236 &file_path)) { |
| 237 continue; |
| 238 } |
| 239 |
| 240 base::File file = OpenNaClReadExecImpl(file_path, true /* executable */); |
| 241 if (!file.IsValid()) |
| 242 continue; |
| 243 |
| 244 // There's no validation caching in Non-SFI mode, so |file_path_metadata| |
| 245 // is unnecessary, and would expose the file path to the plugin. |
| 246 result_list->push_back(NaClResourcePrefetchResult( |
| 247 IPC::TakeFileHandleForProcess(file.Pass(), target_process), |
| 248 uses_nonsfi_mode ? base::FilePath() : file_path, |
| 249 request_list[i].file_key)); |
| 250 } |
| 251 } |
| 252 |
| 253 base::File ReopenNexeFile( |
| 254 base::File original_nexe_file, base::FilePath* nexe_file_path) { |
| 255 // If no path is specified, use the original |nexe_file|. |
| 256 if (!nexe_file_path || nexe_file_path->empty()) |
| 257 return original_nexe_file.Pass(); |
| 258 |
| 259 // Reopen the nexe file. |
| 260 base::File reopened_nexe_file = OpenNaClReadExecImpl( |
| 261 *nexe_file_path, true /* executable */); |
| 262 if (!reopened_nexe_file.IsValid()) { |
| 263 // On fail, clear the path, which will eventually passed to the loader. |
| 264 nexe_file_path->clear(); |
| 265 return original_nexe_file.Pass(); |
| 266 } |
| 267 |
| 268 // Note that, the |original_nexe_file| will be closed automatically. |
| 269 return reopened_nexe_file.Pass(); |
| 270 } |
| 271 |
| 272 // StartNaClExecution needs file operations. This function takes it, and |
| 273 // should run on blocking pool. |
| 274 base::File ResolveNaClFile( |
| 275 base::FilePath* nexe_file_path, |
| 276 base::File nexe_file, |
| 277 const std::vector<NaClResourcePrefetchRequest>& |
| 278 resource_prefetch_request_list, |
| 279 const base::FilePath& profile_directory, |
| 280 base::ProcessHandle target_process, |
| 281 bool uses_nonsfi_mode, |
| 282 std::vector<NaClResourcePrefetchResult>* prefetched_resource_files) { |
| 283 BatchOpenResourceFiles(resource_prefetch_request_list, |
| 284 profile_directory, |
| 285 target_process, |
| 286 uses_nonsfi_mode, |
| 287 prefetched_resource_files); |
| 288 return ReopenNexeFile(nexe_file.Pass(), nexe_file_path); |
199 } | 289 } |
200 | 290 |
201 } // namespace | 291 } // namespace |
202 | 292 |
203 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 293 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
204 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 294 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
205 | 295 |
206 // Unfortunately, we cannot use ScopedGeneric directly for IPC::ChannelHandle, | 296 // Unfortunately, we cannot use ScopedGeneric directly for IPC::ChannelHandle, |
207 // because there is neither operator== nor operator != definition for it. | 297 // because there is neither operator== nor operator != definition for it. |
208 // Instead, define a simple wrapper for IPC::ChannelHandle with an assumption | 298 // Instead, define a simple wrapper for IPC::ChannelHandle with an assumption |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 #endif | 356 #endif |
267 } | 357 } |
268 | 358 |
269 IPC::ChannelHandle handle_; | 359 IPC::ChannelHandle handle_; |
270 }; | 360 }; |
271 | 361 |
272 NaClProcessHost::NaClProcessHost( | 362 NaClProcessHost::NaClProcessHost( |
273 const GURL& manifest_url, | 363 const GURL& manifest_url, |
274 base::File nexe_file, | 364 base::File nexe_file, |
275 const NaClFileToken& nexe_token, | 365 const NaClFileToken& nexe_token, |
276 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, | 366 const std::vector<NaClResourcePrefetchRequest>& |
| 367 resource_prefetch_request_list, |
277 ppapi::PpapiPermissions permissions, | 368 ppapi::PpapiPermissions permissions, |
278 int render_view_id, | 369 int render_view_id, |
279 uint32 permission_bits, | 370 uint32 permission_bits, |
280 bool uses_nonsfi_mode, | 371 bool uses_nonsfi_mode, |
281 bool off_the_record, | 372 bool off_the_record, |
282 NaClAppProcessType process_type, | 373 NaClAppProcessType process_type, |
283 const base::FilePath& profile_directory) | 374 const base::FilePath& profile_directory) |
284 : manifest_url_(manifest_url), | 375 : manifest_url_(manifest_url), |
285 nexe_file_(nexe_file.Pass()), | 376 nexe_file_(nexe_file.Pass()), |
286 nexe_token_(nexe_token), | 377 nexe_token_(nexe_token), |
287 prefetched_resource_files_(prefetched_resource_files), | 378 resource_prefetch_request_list_(resource_prefetch_request_list), |
288 permissions_(permissions), | 379 permissions_(permissions), |
289 #if defined(OS_WIN) | 380 #if defined(OS_WIN) |
290 process_launched_by_broker_(false), | 381 process_launched_by_broker_(false), |
291 #endif | 382 #endif |
292 reply_msg_(NULL), | 383 reply_msg_(NULL), |
293 #if defined(OS_WIN) | 384 #if defined(OS_WIN) |
294 debug_exception_handler_requested_(false), | 385 debug_exception_handler_requested_(false), |
295 #endif | 386 #endif |
296 uses_nonsfi_mode_(uses_nonsfi_mode), | 387 uses_nonsfi_mode_(uses_nonsfi_mode), |
297 enable_debug_stub_(false), | 388 enable_debug_stub_(false), |
(...skipping 12 matching lines...) Expand all Loading... |
310 // for this use case. | 401 // for this use case. |
311 process_->SetName(net::FormatUrl(manifest_url_, std::string())); | 402 process_->SetName(net::FormatUrl(manifest_url_, std::string())); |
312 | 403 |
313 enable_debug_stub_ = base::CommandLine::ForCurrentProcess()->HasSwitch( | 404 enable_debug_stub_ = base::CommandLine::ForCurrentProcess()->HasSwitch( |
314 switches::kEnableNaClDebug); | 405 switches::kEnableNaClDebug); |
315 DCHECK(process_type_ != kUnknownNaClProcessType); | 406 DCHECK(process_type_ != kUnknownNaClProcessType); |
316 enable_crash_throttling_ = process_type_ != kNativeNaClProcessType; | 407 enable_crash_throttling_ = process_type_ != kNativeNaClProcessType; |
317 } | 408 } |
318 | 409 |
319 NaClProcessHost::~NaClProcessHost() { | 410 NaClProcessHost::~NaClProcessHost() { |
| 411 PostCloseFile(nexe_file_.Pass()); |
| 412 PostCloseFile(socket_for_renderer_.Pass()); |
| 413 PostCloseFile(socket_for_sel_ldr_.Pass()); |
| 414 |
320 // Report exit status only if the process was successfully started. | 415 // Report exit status only if the process was successfully started. |
321 if (process_->GetData().handle != base::kNullProcessHandle) { | 416 if (process_->GetData().handle != base::kNullProcessHandle) { |
322 int exit_code = 0; | 417 int exit_code = 0; |
323 process_->GetTerminationStatus(false /* known_dead */, &exit_code); | 418 process_->GetTerminationStatus(false /* known_dead */, &exit_code); |
324 std::string message = | 419 std::string message = |
325 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 420 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
326 exit_code, exit_code); | 421 exit_code, exit_code); |
327 if (exit_code == 0) { | 422 if (exit_code == 0) { |
328 VLOG(1) << message; | 423 VLOG(1) << message; |
329 } else { | 424 } else { |
330 LOG(ERROR) << message; | 425 LOG(ERROR) << message; |
331 } | 426 } |
332 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); | 427 NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id); |
333 } | 428 } |
334 | 429 |
335 // Note: this does not work on Windows, though we currently support this | |
336 // prefetching feature only on POSIX platforms, so it should be ok. | |
337 #if defined(OS_WIN) | |
338 DCHECK(prefetched_resource_files_.empty()); | |
339 #else | |
340 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { | |
341 // The process failed to launch for some reason. Close resource file | |
342 // handles. | |
343 base::File file(IPC::PlatformFileForTransitToFile( | |
344 prefetched_resource_files_[i].file)); | |
345 content::BrowserThread::GetBlockingPool()->PostTask( | |
346 FROM_HERE, | |
347 base::Bind(&CloseFile, base::Passed(file.Pass()))); | |
348 } | |
349 #endif | |
350 | |
351 if (reply_msg_) { | 430 if (reply_msg_) { |
352 // The process failed to launch for some reason. | 431 // The process failed to launch for some reason. |
353 // Don't keep the renderer hanging. | 432 // Don't keep the renderer hanging. |
354 reply_msg_->set_reply_error(); | 433 reply_msg_->set_reply_error(); |
355 nacl_host_message_filter_->Send(reply_msg_); | 434 nacl_host_message_filter_->Send(reply_msg_); |
356 } | 435 } |
357 #if defined(OS_WIN) | 436 #if defined(OS_WIN) |
358 if (process_launched_by_broker_) { | 437 if (process_launched_by_broker_) { |
359 NaClBrokerService::GetInstance()->OnLoaderDied(); | 438 NaClBrokerService::GetInstance()->OnLoaderDied(); |
360 } | 439 } |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 bool NaClProcessHost::StartNaClExecution() { | 937 bool NaClProcessHost::StartNaClExecution() { |
859 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 938 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
860 | 939 |
861 NaClStartParams params; | 940 NaClStartParams params; |
862 | 941 |
863 // Enable PPAPI proxy channel creation only for renderer processes. | 942 // Enable PPAPI proxy channel creation only for renderer processes. |
864 params.enable_ipc_proxy = enable_ppapi_proxy(); | 943 params.enable_ipc_proxy = enable_ppapi_proxy(); |
865 params.process_type = process_type_; | 944 params.process_type = process_type_; |
866 bool enable_nacl_debug = enable_debug_stub_ && | 945 bool enable_nacl_debug = enable_debug_stub_ && |
867 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); | 946 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); |
| 947 #if defined(OS_MACOSX) |
| 948 base::ScopedFD memory_fd; |
| 949 #endif // defined(OS_MACOSX) |
| 950 #if defined(OS_POSIX) |
| 951 base::ScopedFD debug_stub_server_bound_socket; |
| 952 #endif // defined(OS_POSIX) |
| 953 |
868 if (uses_nonsfi_mode_) { | 954 if (uses_nonsfi_mode_) { |
869 // Currently, non-SFI mode is supported only on Linux. | 955 // Currently, non-SFI mode is supported only on Linux. |
870 #if defined(OS_LINUX) | 956 #if defined(OS_LINUX) |
871 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is | 957 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is |
872 // not created. | 958 // not created. |
873 DCHECK(!socket_for_sel_ldr_.IsValid()); | 959 DCHECK(!socket_for_sel_ldr_.IsValid()); |
874 #endif | 960 #endif |
875 if (enable_nacl_debug) { | 961 if (enable_nacl_debug) { |
876 base::ProcessId pid = base::GetProcId(process_->GetData().handle); | 962 base::ProcessId pid = base::GetProcId(process_->GetData().handle); |
877 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; | 963 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; |
878 } | 964 } |
879 } else { | 965 } else { |
880 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 966 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
881 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 967 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
882 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 968 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
883 params.enable_debug_stub = enable_nacl_debug; | 969 params.enable_debug_stub = enable_nacl_debug; |
884 | 970 |
885 const ChildProcessData& data = process_->GetData(); | 971 CHECK(nacl_browser->IrtFile().IsValid()); |
886 params.imc_bootstrap_handle = | |
887 IPC::TakeFileHandleForProcess(socket_for_sel_ldr_.Pass(), data.handle); | |
888 if (params.imc_bootstrap_handle == IPC::InvalidPlatformFileForTransit()) { | |
889 return false; | |
890 } | |
891 | |
892 const base::File& irt_file = nacl_browser->IrtFile(); | |
893 CHECK(irt_file.IsValid()); | |
894 // Send over the IRT file handle. We don't close our own copy! | |
895 params.irt_handle = IPC::GetFileHandleForProcess( | |
896 irt_file.GetPlatformFile(), data.handle, false); | |
897 if (params.irt_handle == IPC::InvalidPlatformFileForTransit()) { | |
898 return false; | |
899 } | |
900 | 972 |
901 #if defined(OS_MACOSX) | 973 #if defined(OS_MACOSX) |
902 // For dynamic loading support, NaCl requires a file descriptor that | 974 // For dynamic loading support, NaCl requires a file descriptor that |
903 // was created in /tmp, since those created with shm_open() are not | 975 // was created in /tmp, since those created with shm_open() are not |
904 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 976 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
905 // round trip out of the sandbox, we create an FD here. | 977 // round trip out of the sandbox, we create an FD here. |
906 base::SharedMemory memory_buffer; | 978 base::SharedMemory memory_buffer; |
907 base::SharedMemoryCreateOptions options; | 979 base::SharedMemoryCreateOptions options; |
908 options.size = 1; | 980 options.size = 1; |
909 options.executable = true; | 981 options.executable = true; |
910 if (!memory_buffer.Create(options)) { | 982 if (!memory_buffer.Create(options)) { |
911 DLOG(ERROR) << "Failed to allocate memory buffer"; | 983 DLOG(ERROR) << "Failed to allocate memory buffer"; |
912 return false; | 984 return false; |
913 } | 985 } |
914 base::ScopedFD memory_fd(dup(memory_buffer.handle().fd)); | 986 memory_fd.reset(dup(memory_buffer.handle().fd)); |
915 if (!memory_fd.is_valid()) { | 987 if (!memory_fd.is_valid()) { |
916 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 988 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
917 return false; | 989 return false; |
918 } | 990 } |
919 params.mac_shm_fd = IPC::GetFileHandleForProcess( | |
920 memory_fd.release(), data.handle, true); | |
921 #endif | 991 #endif |
922 | 992 |
923 #if defined(OS_POSIX) | 993 #if defined(OS_POSIX) |
924 if (params.enable_debug_stub) { | 994 if (params.enable_debug_stub) |
925 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 995 debug_stub_server_bound_socket.reset(GetDebugStubSocketHandle()); |
926 if (server_bound_socket != net::kInvalidSocket) { | |
927 params.debug_stub_server_bound_socket = IPC::GetFileHandleForProcess( | |
928 server_bound_socket, data.handle, true); | |
929 } | |
930 } | |
931 #endif | 996 #endif |
932 } | 997 } |
933 | 998 |
934 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, | 999 // Transfer resources to |params|. |
935 ¶ms.crash_info_shmem_handle)) { | 1000 // Hereafter, we should never return false, and should always send an IPC |
936 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; | 1001 // to NaCl plugin process. Otherwise, the resources passed to |params| may |
937 return false; | 1002 // be leaked. Note that these are resources for Plugin process, so we |
938 } | 1003 // cannot properly release those in this (browser) process. |
| 1004 { |
| 1005 const ChildProcessData& data = process_->GetData(); |
| 1006 if (!uses_nonsfi_mode_) { |
| 1007 params.imc_bootstrap_handle = IPC::TakeFileHandleForProcess( |
| 1008 socket_for_sel_ldr_.Pass(), data.handle); |
| 1009 // Send over the IRT file handle. We don't close our own copy! |
| 1010 params.irt_handle = IPC::GetFileHandleForProcess( |
| 1011 nacl_browser->IrtFile().GetPlatformFile(), data.handle, false); |
939 | 1012 |
940 // Pass the pre-opened resource files to the loader. We do not have to reopen | 1013 #if defined(OS_MACOSX) |
941 // resource files here even for SFI mode because the descriptors are not from | 1014 params.mac_shm_fd = IPC::GetFileHandleForProcess( |
942 // a renderer. | 1015 memory_fd.release(), data.handle, true); |
943 for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { | 1016 #endif |
944 process_->Send(new NaClProcessMsg_AddPrefetchedResource( | 1017 #if defined(OS_POSIX) |
945 NaClResourcePrefetchResult( | 1018 params.debug_stub_server_bound_socket = IPC::GetFileHandleForProcess( |
946 prefetched_resource_files_[i].file, | 1019 debug_stub_server_bound_socket.release(), data.handle, true); |
947 // For the same reason as the comment below, always use an empty | 1020 #endif |
948 // base::FilePath for non-SFI mode. | 1021 } |
949 (uses_nonsfi_mode_ ? base::FilePath() : | |
950 prefetched_resource_files_[i].file_path_metadata), | |
951 prefetched_resource_files_[i].file_key))); | |
952 } | |
953 prefetched_resource_files_.clear(); | |
954 | 1022 |
955 base::FilePath file_path; | 1023 if (!crash_info_shmem_.ShareToProcess(data.handle, |
956 if (uses_nonsfi_mode_) { | 1024 ¶ms.crash_info_shmem_handle)) { |
957 // Don't retrieve the file path when using nonsfi mode; there's no | 1025 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; |
958 // validation caching in that case, so it's unnecessary work, and would | 1026 // Do not return here. |
959 // expose the file path to the plugin. | |
960 } else { | |
961 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, | |
962 nexe_token_.hi, | |
963 &file_path)) { | |
964 // We have to reopen the file in the browser process; we don't want a | |
965 // compromised renderer to pass an arbitrary fd that could get loaded | |
966 // into the plugin process. | |
967 if (base::PostTaskAndReplyWithResult( | |
968 content::BrowserThread::GetBlockingPool(), | |
969 FROM_HERE, | |
970 base::Bind(OpenNaClReadExecImpl, | |
971 file_path, | |
972 true /* is_executable */), | |
973 base::Bind(&NaClProcessHost::StartNaClFileResolved, | |
974 weak_factory_.GetWeakPtr(), | |
975 params, | |
976 file_path))) { | |
977 return true; | |
978 } | |
979 } | 1027 } |
980 } | 1028 } |
981 | 1029 |
982 StartNaClFileResolved(params, base::FilePath(), base::File()); | 1030 // We have to reopen the file in the browser process; we don't want a |
| 1031 // compromised renderer to pass an arbitrary fd that could get loaded |
| 1032 // into the plugin process. |
| 1033 // Don't retrieve the file path when using nonsfi mode; there's no |
| 1034 // validation caching in that case, so it's unnecessary work, and would |
| 1035 // expose the file path to the plugin. |
| 1036 scoped_ptr<base::FilePath> nexe_file_path; |
| 1037 if (!uses_nonsfi_mode_) { |
| 1038 nexe_file_path.reset(new base::FilePath); |
| 1039 if (!NaClBrowser::GetInstance()->GetFilePath( |
| 1040 nexe_token_.lo, nexe_token_.hi, nexe_file_path.get())) { |
| 1041 // Failed. Reset the pointer. |
| 1042 nexe_file_path.reset(); |
| 1043 } |
| 1044 } |
| 1045 |
| 1046 // Pass the pre-opened resource files to the loader. |
| 1047 scoped_ptr<std::vector<NaClResourcePrefetchResult> > |
| 1048 prefetched_resource_files; |
| 1049 if (!resource_prefetch_request_list_.empty()) { |
| 1050 prefetched_resource_files.reset( |
| 1051 new std::vector<NaClResourcePrefetchResult>); |
| 1052 } |
| 1053 |
| 1054 // If file operation is necessary, run it on a blocking pool, where file |
| 1055 // operations are allowed. |
| 1056 if (nexe_file_path.get() || prefetched_resource_files.get()) { |
| 1057 if (base::PostTaskAndReplyWithResult( |
| 1058 content::BrowserThread::GetBlockingPool(), |
| 1059 FROM_HERE, |
| 1060 base::Bind(&ResolveNaClFile, |
| 1061 nexe_file_path.get(), |
| 1062 base::Passed(&nexe_file_), |
| 1063 resource_prefetch_request_list_, |
| 1064 profile_directory_, |
| 1065 process_->GetData().handle, |
| 1066 uses_nonsfi_mode_, |
| 1067 prefetched_resource_files.get()), |
| 1068 base::Bind(&NaClProcessHost::StartNaClExecutionAfterFileResolved, |
| 1069 weak_factory_.GetWeakPtr(), |
| 1070 params, |
| 1071 base::Passed(&nexe_file_path), |
| 1072 base::Passed(&prefetched_resource_files)))) { |
| 1073 return true; |
| 1074 } |
| 1075 } |
| 1076 |
| 1077 StartNaClExecutionAfterFileResolved( |
| 1078 params, |
| 1079 scoped_ptr<base::FilePath>(), |
| 1080 scoped_ptr<std::vector<NaClResourcePrefetchResult> >(), |
| 1081 nexe_file_.Pass()); |
983 return true; | 1082 return true; |
984 } | 1083 } |
985 | 1084 |
986 void NaClProcessHost::StartNaClFileResolved( | 1085 void NaClProcessHost::StartNaClExecutionAfterFileResolved( |
987 NaClStartParams params, | 1086 NaClStartParams params, |
988 const base::FilePath& file_path, | 1087 scoped_ptr<base::FilePath> nexe_file_path, |
989 base::File checked_nexe_file) { | 1088 scoped_ptr<std::vector<NaClResourcePrefetchResult> > |
990 if (checked_nexe_file.IsValid()) { | 1089 prefetched_resource_files, |
991 // Release the file received from the renderer. This has to be done on a | 1090 base::File nexe_file) { |
992 // thread where IO is permitted, though. | 1091 // Pass the pre-opened resource files to the loader. |
993 content::BrowserThread::GetBlockingPool()->PostTask( | 1092 if (prefetched_resource_files.get()) { |
994 FROM_HERE, | 1093 for (size_t i = 0; i < prefetched_resource_files->size(); ++i) { |
995 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); | 1094 process_->Send(new NaClProcessMsg_AddPrefetchedResource( |
996 params.nexe_file_path_metadata = file_path; | 1095 (*prefetched_resource_files)[i])); |
997 params.nexe_file = IPC::TakeFileHandleForProcess( | 1096 } |
998 checked_nexe_file.Pass(), process_->GetData().handle); | |
999 } else { | |
1000 params.nexe_file = IPC::TakeFileHandleForProcess( | |
1001 nexe_file_.Pass(), process_->GetData().handle); | |
1002 } | 1097 } |
1003 | 1098 |
1004 #if defined(OS_LINUX) | 1099 #if defined(OS_LINUX) |
1005 // In Non-SFI mode, create socket pairs for IPC channels here, unlike in | 1100 // In Non-SFI mode, create socket pairs for IPC channels here, unlike in |
1006 // SFI-mode, in which those channels are created in nacl_listener.cc. | 1101 // SFI-mode, in which those channels are created in nacl_listener.cc. |
1007 // This is for security hardening. We can then prohibit the socketpair() | 1102 // This is for security hardening. We can then prohibit the socketpair() |
1008 // system call in nacl_helper and nacl_helper_nonsfi. | 1103 // system call in nacl_helper and nacl_helper_nonsfi. |
1009 if (uses_nonsfi_mode_) { | 1104 if (uses_nonsfi_mode_) { |
1010 // Note: here, because some FDs/handles for the NaCl loader process are | 1105 // Note: here, because some FDs/handles for the NaCl loader process are |
1011 // already opened, they are transferred to NaCl loader process even if | 1106 // already opened, they are transferred to NaCl loader process even if |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 params.ppapi_renderer_channel_handle = | 1151 params.ppapi_renderer_channel_handle = |
1057 ppapi_renderer_server_channel_handle.release(); | 1152 ppapi_renderer_server_channel_handle.release(); |
1058 params.trusted_service_channel_handle = | 1153 params.trusted_service_channel_handle = |
1059 trusted_service_server_channel_handle.release(); | 1154 trusted_service_server_channel_handle.release(); |
1060 params.manifest_service_channel_handle = | 1155 params.manifest_service_channel_handle = |
1061 manifest_service_server_channel_handle.release(); | 1156 manifest_service_server_channel_handle.release(); |
1062 } | 1157 } |
1063 } | 1158 } |
1064 #endif | 1159 #endif |
1065 | 1160 |
| 1161 // Pass the nexe file and its path to params. |
| 1162 params.nexe_file = IPC::TakeFileHandleForProcess( |
| 1163 nexe_file.Pass(), process_->GetData().handle); |
| 1164 if (nexe_file_path.get()) { |
| 1165 params.nexe_file_path_metadata = *nexe_file_path; |
| 1166 } |
| 1167 |
1066 process_->Send(new NaClProcessMsg_Start(params)); | 1168 process_->Send(new NaClProcessMsg_Start(params)); |
1067 } | 1169 } |
1068 | 1170 |
1069 #if defined(OS_LINUX) | 1171 #if defined(OS_LINUX) |
1070 // static | 1172 // static |
1071 bool NaClProcessHost::CreateChannelHandlePair( | 1173 bool NaClProcessHost::CreateChannelHandlePair( |
1072 ScopedChannelHandle* channel_handle1, | 1174 ScopedChannelHandle* channel_handle1, |
1073 ScopedChannelHandle* channel_handle2) { | 1175 ScopedChannelHandle* channel_handle2) { |
1074 DCHECK(channel_handle1); | 1176 DCHECK(channel_handle1); |
1075 DCHECK(channel_handle2); | 1177 DCHECK(channel_handle2); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 process.Pass(), info, | 1455 process.Pass(), info, |
1354 base::MessageLoopProxy::current(), | 1456 base::MessageLoopProxy::current(), |
1355 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1457 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1356 weak_factory_.GetWeakPtr())); | 1458 weak_factory_.GetWeakPtr())); |
1357 return true; | 1459 return true; |
1358 } | 1460 } |
1359 } | 1461 } |
1360 #endif | 1462 #endif |
1361 | 1463 |
1362 } // namespace nacl | 1464 } // namespace nacl |
OLD | NEW |