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 |