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 |