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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 reinterpret_cast<nacl::FileDescriptor>(channel)); | 223 reinterpret_cast<nacl::FileDescriptor>(channel)); |
224 #else | 224 #else |
225 nacl::FileDescriptor channel; | 225 nacl::FileDescriptor channel; |
226 channel.fd = sourceh; | 226 channel.fd = sourceh; |
227 channel.auto_close = close_source; | 227 channel.auto_close = close_source; |
228 handles_for_sel_ldr->push_back(channel); | 228 handles_for_sel_ldr->push_back(channel); |
229 #endif | 229 #endif |
230 return true; | 230 return true; |
231 } | 231 } |
232 | 232 |
233 void CloseFile(base::File file) { | |
234 // The base::File destructor will close the file for us. | |
235 } | |
236 | |
233 } // namespace | 237 } // namespace |
234 | 238 |
235 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 239 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
236 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 240 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
237 | 241 |
238 NaClProcessHost::NaClProcessHost(const GURL& manifest_url, | 242 NaClProcessHost::NaClProcessHost(const GURL& manifest_url, |
239 base::File nexe_file, | 243 base::File nexe_file, |
240 const NaClFileToken& nexe_token, | 244 const NaClFileToken& nexe_token, |
241 ppapi::PpapiPermissions permissions, | 245 ppapi::PpapiPermissions permissions, |
242 int render_view_id, | 246 int render_view_id, |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
625 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 629 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, |
626 OnPpapiChannelsCreated) | 630 OnPpapiChannelsCreated) |
627 IPC_MESSAGE_UNHANDLED(handled = false) | 631 IPC_MESSAGE_UNHANDLED(handled = false) |
628 IPC_END_MESSAGE_MAP() | 632 IPC_END_MESSAGE_MAP() |
629 } else { | 633 } else { |
630 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 634 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) |
631 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, | 635 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, |
632 OnQueryKnownToValidate) | 636 OnQueryKnownToValidate) |
633 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, | 637 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, |
634 OnSetKnownToValidate) | 638 OnSetKnownToValidate) |
635 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_ResolveFileToken, | 639 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken, |
636 OnResolveFileToken) | 640 OnResolveFileToken) |
637 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileTokenAsync, | |
638 OnResolveFileTokenAsync) | |
639 | 641 |
640 #if defined(OS_WIN) | 642 #if defined(OS_WIN) |
641 IPC_MESSAGE_HANDLER_DELAY_REPLY( | 643 IPC_MESSAGE_HANDLER_DELAY_REPLY( |
642 NaClProcessMsg_AttachDebugExceptionHandler, | 644 NaClProcessMsg_AttachDebugExceptionHandler, |
643 OnAttachDebugExceptionHandler) | 645 OnAttachDebugExceptionHandler) |
644 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, | 646 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, |
645 OnDebugStubPortSelected) | 647 OnDebugStubPortSelected) |
646 #endif | 648 #endif |
647 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 649 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, |
648 OnPpapiChannelsCreated) | 650 OnPpapiChannelsCreated) |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 // not created. | 817 // not created. |
816 DCHECK(!socket_for_sel_ldr_.IsValid()); | 818 DCHECK(!socket_for_sel_ldr_.IsValid()); |
817 #endif | 819 #endif |
818 } else { | 820 } else { |
819 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 821 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
820 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 822 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
821 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 823 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
822 params.enable_debug_stub = enable_debug_stub_ && | 824 params.enable_debug_stub = enable_debug_stub_ && |
823 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); | 825 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); |
824 | 826 |
825 // TODO(teravest): Resolve the file tokens right now instead of making the | |
826 // loader send IPC to resolve them later. | |
827 params.nexe_token_lo = nexe_token_.lo; | |
828 params.nexe_token_hi = nexe_token_.hi; | |
829 | |
830 const ChildProcessData& data = process_->GetData(); | 827 const ChildProcessData& data = process_->GetData(); |
831 if (!ShareHandleToSelLdr(data.handle, | 828 if (!ShareHandleToSelLdr(data.handle, |
832 socket_for_sel_ldr_.TakePlatformFile(), | 829 socket_for_sel_ldr_.TakePlatformFile(), |
833 true, | 830 true, |
834 ¶ms.handles)) { | 831 ¶ms.handles)) { |
835 return false; | 832 return false; |
836 } | 833 } |
837 | 834 |
838 // Currently, everything uses the IRT except for the PNaCl Translators. | 835 // Currently, everything uses the IRT except for the PNaCl Translators. |
839 bool uses_irt = process_type_ != kPNaClTranslatorProcessType; | 836 bool uses_irt = process_type_ != kPNaClTranslatorProcessType; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
874 if (params.enable_debug_stub) { | 871 if (params.enable_debug_stub) { |
875 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 872 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); |
876 if (server_bound_socket != net::kInvalidSocket) { | 873 if (server_bound_socket != net::kInvalidSocket) { |
877 params.debug_stub_server_bound_socket = | 874 params.debug_stub_server_bound_socket = |
878 FileDescriptor(server_bound_socket, true); | 875 FileDescriptor(server_bound_socket, true); |
879 } | 876 } |
880 } | 877 } |
881 #endif | 878 #endif |
882 } | 879 } |
883 | 880 |
884 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | |
885 process_->GetData().handle); | |
886 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, | 881 if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle, |
887 ¶ms.crash_info_shmem_handle)) { | 882 ¶ms.crash_info_shmem_handle)) { |
888 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; | 883 DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer"; |
889 return false; | 884 return false; |
890 } | 885 } |
891 | 886 |
887 base::FilePath file_path; | |
888 if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, | |
Yusuke Sato
2014/10/20 18:55:08
Is this necessary for non-sfi? Maybe
if (!uses_n
Yusuke Sato
2014/10/21 21:51:52
and do you mean
if (!NaClBrowser::GetInstance()->
teravest
2014/10/23 17:20:26
Done.
| |
889 nexe_token_.hi, | |
890 &file_path)) { | |
891 // We have to reopen the file in the browser process; we don't want a | |
892 // compromised renderer to pass an arbitrary fd that could get loaded | |
893 // into the plugin process. | |
894 if (base::PostTaskAndReplyWithResult( | |
895 content::BrowserThread::GetBlockingPool(), | |
896 FROM_HERE, | |
897 base::Bind(OpenNaClReadExecImpl, | |
898 file_path, | |
899 true /* is_executable */), | |
900 base::Bind(&NaClProcessHost::StartNaClFileResolved, | |
901 weak_factory_.GetWeakPtr(), | |
902 params, | |
903 file_path))) { | |
904 return true; | |
905 } | |
906 } | |
907 | |
908 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | |
909 process_->GetData().handle); | |
892 process_->Send(new NaClProcessMsg_Start(params)); | 910 process_->Send(new NaClProcessMsg_Start(params)); |
893 return true; | 911 return true; |
894 } | 912 } |
895 | 913 |
914 void NaClProcessHost::StartNaClFileResolved( | |
915 NaClStartParams params, | |
916 const base::FilePath& file_path, | |
917 base::File checked_nexe_file) { | |
918 if (checked_nexe_file.IsValid()) { | |
919 // Release the file received from the renderer. This has to be done on a | |
920 // thread where IO is permitted, though. | |
921 content::BrowserThread::GetBlockingPool()->PostTask( | |
922 FROM_HERE, | |
923 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); | |
924 params.nexe_file_path_metadata = file_path; | |
925 params.nexe_file = IPC::TakeFileHandleForProcess( | |
926 checked_nexe_file.Pass(), process_->GetData().handle); | |
927 } else { | |
928 params.nexe_file = IPC::TakeFileHandleForProcess( | |
929 nexe_file_.Pass(), process_->GetData().handle); | |
930 } | |
931 process_->Send(new NaClProcessMsg_Start(params)); | |
932 } | |
933 | |
896 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 934 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is |
897 // received. | 935 // received. |
898 void NaClProcessHost::OnPpapiChannelsCreated( | 936 void NaClProcessHost::OnPpapiChannelsCreated( |
899 const IPC::ChannelHandle& browser_channel_handle, | 937 const IPC::ChannelHandle& browser_channel_handle, |
900 const IPC::ChannelHandle& ppapi_renderer_channel_handle, | 938 const IPC::ChannelHandle& ppapi_renderer_channel_handle, |
901 const IPC::ChannelHandle& trusted_renderer_channel_handle, | 939 const IPC::ChannelHandle& trusted_renderer_channel_handle, |
902 const IPC::ChannelHandle& manifest_service_channel_handle) { | 940 const IPC::ChannelHandle& manifest_service_channel_handle) { |
903 if (!enable_ppapi_proxy()) { | 941 if (!enable_ppapi_proxy()) { |
904 ReplyToRenderer(IPC::ChannelHandle(), | 942 ReplyToRenderer(IPC::ChannelHandle(), |
905 trusted_renderer_channel_handle, | 943 trusted_renderer_channel_handle, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
989 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); | 1027 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); |
990 } | 1028 } |
991 | 1029 |
992 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { | 1030 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { |
993 CHECK(!uses_nonsfi_mode_); | 1031 CHECK(!uses_nonsfi_mode_); |
994 NaClBrowser::GetInstance()->SetKnownToValidate( | 1032 NaClBrowser::GetInstance()->SetKnownToValidate( |
995 signature, off_the_record_); | 1033 signature, off_the_record_); |
996 } | 1034 } |
997 | 1035 |
998 void NaClProcessHost::OnResolveFileToken(uint64 file_token_lo, | 1036 void NaClProcessHost::OnResolveFileToken(uint64 file_token_lo, |
999 uint64 file_token_hi, | 1037 uint64 file_token_hi) { |
1000 IPC::Message* reply_msg) { | |
1001 // Was the file registered? | 1038 // Was the file registered? |
1002 // | 1039 // |
1003 // Note that the file path cache is of bounded size, and old entries can get | 1040 // Note that the file path cache is of bounded size, and old entries can get |
1004 // evicted. If a large number of NaCl modules are being launched at once, | 1041 // evicted. If a large number of NaCl modules are being launched at once, |
1005 // resolving the file_token may fail because the path cache was thrashed | 1042 // resolving the file_token may fail because the path cache was thrashed |
1006 // while the file_token was in flight. In this case the query fails, and we | 1043 // while the file_token was in flight. In this case the query fails, and we |
1007 // need to fall back to the slower path. | 1044 // need to fall back to the slower path. |
1008 // | 1045 // |
1009 // However: each NaCl process will consume 2-3 entries as it starts up, this | 1046 // However: each NaCl process will consume 2-3 entries as it starts up, this |
1010 // means that eviction will not happen unless you start up 33+ NaCl processes | 1047 // means that eviction will not happen unless you start up 33+ NaCl processes |
1011 // at the same time, and this still requires worst-case timing. As a | 1048 // at the same time, and this still requires worst-case timing. As a |
1012 // practical matter, no entries should be evicted prematurely. | 1049 // practical matter, no entries should be evicted prematurely. |
1013 // The cache itself should take ~ (150 characters * 2 bytes/char + ~60 bytes | 1050 // The cache itself should take ~ (150 characters * 2 bytes/char + ~60 bytes |
1014 // data structure overhead) * 100 = 35k when full, so making it bigger should | 1051 // data structure overhead) * 100 = 35k when full, so making it bigger should |
1015 // not be a problem, if needed. | 1052 // not be a problem, if needed. |
1016 // | 1053 // |
1017 // Each NaCl process will consume 2-3 entries because the manifest and main | 1054 // Each NaCl process will consume 2-3 entries because the manifest and main |
1018 // nexe are currently not resolved. Shared libraries will be resolved. They | 1055 // nexe are currently not resolved. Shared libraries will be resolved. They |
1019 // will be loaded sequentially, so they will only consume a single entry | 1056 // will be loaded sequentially, so they will only consume a single entry |
1020 // while the load is in flight. | 1057 // while the load is in flight. |
1021 // | 1058 // |
1022 // TODO(ncbray): track behavior with UMA. If entries are getting evicted or | 1059 // TODO(ncbray): track behavior with UMA. If entries are getting evicted or |
1023 // bogus keys are getting queried, this would be good to know. | 1060 // bogus keys are getting queried, this would be good to know. |
1024 CHECK(!uses_nonsfi_mode_); | 1061 CHECK(!uses_nonsfi_mode_); |
1025 base::FilePath file_path; | 1062 base::FilePath file_path; |
1026 if (!NaClBrowser::GetInstance()->GetFilePath( | 1063 if (!NaClBrowser::GetInstance()->GetFilePath( |
1027 file_token_lo, file_token_hi, &file_path)) { | 1064 file_token_lo, file_token_hi, &file_path)) { |
1028 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | 1065 Send(new NaClProcessMsg_ResolveFileTokenReply( |
1029 reply_msg, | |
1030 IPC::InvalidPlatformFileForTransit(), | |
1031 base::FilePath()); | |
1032 Send(reply_msg); | |
1033 return; | |
1034 } | |
1035 | |
1036 // Open the file. | |
1037 if (!base::PostTaskAndReplyWithResult( | |
1038 content::BrowserThread::GetBlockingPool(), | |
1039 FROM_HERE, | |
1040 base::Bind(OpenNaClReadExecImpl, file_path, true /* is_executable */), | |
1041 base::Bind(&NaClProcessHost::FileResolved, | |
1042 weak_factory_.GetWeakPtr(), | |
1043 file_path, | |
1044 reply_msg))) { | |
1045 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | |
1046 reply_msg, | |
1047 IPC::InvalidPlatformFileForTransit(), | |
1048 base::FilePath()); | |
1049 Send(reply_msg); | |
1050 } | |
1051 } | |
1052 | |
1053 void NaClProcessHost::OnResolveFileTokenAsync(uint64 file_token_lo, | |
1054 uint64 file_token_hi) { | |
1055 // See the comment at OnResolveFileToken() for details of the file path cache | |
1056 // behavior. | |
1057 CHECK(!uses_nonsfi_mode_); | |
1058 base::FilePath file_path; | |
1059 if (!NaClBrowser::GetInstance()->GetFilePath( | |
1060 file_token_lo, file_token_hi, &file_path)) { | |
1061 Send(new NaClProcessMsg_ResolveFileTokenAsyncReply( | |
1062 file_token_lo, | 1066 file_token_lo, |
1063 file_token_hi, | 1067 file_token_hi, |
1064 IPC::PlatformFileForTransit(), | 1068 IPC::PlatformFileForTransit(), |
1065 base::FilePath())); | 1069 base::FilePath())); |
1066 return; | 1070 return; |
1067 } | 1071 } |
1068 | 1072 |
1069 // Open the file. | 1073 // Open the file. |
1070 if (!base::PostTaskAndReplyWithResult( | 1074 if (!base::PostTaskAndReplyWithResult( |
1071 content::BrowserThread::GetBlockingPool(), | 1075 content::BrowserThread::GetBlockingPool(), |
1072 FROM_HERE, | 1076 FROM_HERE, |
1073 base::Bind(OpenNaClReadExecImpl, file_path, true /* is_executable */), | 1077 base::Bind(OpenNaClReadExecImpl, file_path, true /* is_executable */), |
1074 base::Bind(&NaClProcessHost::FileResolvedAsync, | 1078 base::Bind(&NaClProcessHost::FileResolved, |
1075 weak_factory_.GetWeakPtr(), | 1079 weak_factory_.GetWeakPtr(), |
1076 file_token_lo, | 1080 file_token_lo, |
1077 file_token_hi, | 1081 file_token_hi, |
1078 file_path))) { | 1082 file_path))) { |
1079 Send(new NaClProcessMsg_ResolveFileTokenAsyncReply( | 1083 Send(new NaClProcessMsg_ResolveFileTokenReply( |
1080 file_token_lo, | 1084 file_token_lo, |
1081 file_token_hi, | 1085 file_token_hi, |
1082 IPC::PlatformFileForTransit(), | 1086 IPC::PlatformFileForTransit(), |
1083 base::FilePath())); | 1087 base::FilePath())); |
1084 } | 1088 } |
1085 } | 1089 } |
1086 | 1090 |
1087 void NaClProcessHost::FileResolved( | 1091 void NaClProcessHost::FileResolved( |
1088 const base::FilePath& file_path, | |
1089 IPC::Message* reply_msg, | |
1090 base::File file) { | |
1091 if (file.IsValid()) { | |
1092 IPC::PlatformFileForTransit handle = IPC::TakeFileHandleForProcess( | |
1093 file.Pass(), | |
1094 process_->GetData().handle); | |
1095 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | |
1096 reply_msg, | |
1097 handle, | |
1098 file_path); | |
1099 } else { | |
1100 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | |
1101 reply_msg, | |
1102 IPC::InvalidPlatformFileForTransit(), | |
1103 base::FilePath()); | |
1104 } | |
1105 Send(reply_msg); | |
1106 } | |
1107 | |
1108 void NaClProcessHost::FileResolvedAsync( | |
1109 uint64_t file_token_lo, | 1092 uint64_t file_token_lo, |
1110 uint64_t file_token_hi, | 1093 uint64_t file_token_hi, |
1111 const base::FilePath& file_path, | 1094 const base::FilePath& file_path, |
1112 base::File file) { | 1095 base::File file) { |
1113 base::FilePath out_file_path; | 1096 base::FilePath out_file_path; |
1114 IPC::PlatformFileForTransit out_handle; | 1097 IPC::PlatformFileForTransit out_handle; |
1115 if (file.IsValid()) { | 1098 if (file.IsValid()) { |
1116 out_file_path = file_path; | 1099 out_file_path = file_path; |
1117 out_handle = IPC::TakeFileHandleForProcess( | 1100 out_handle = IPC::TakeFileHandleForProcess( |
1118 file.Pass(), | 1101 file.Pass(), |
1119 process_->GetData().handle); | 1102 process_->GetData().handle); |
1120 } else { | 1103 } else { |
1121 out_handle = IPC::InvalidPlatformFileForTransit(); | 1104 out_handle = IPC::InvalidPlatformFileForTransit(); |
1122 } | 1105 } |
1123 Send(new NaClProcessMsg_ResolveFileTokenAsyncReply( | 1106 Send(new NaClProcessMsg_ResolveFileTokenReply( |
1124 file_token_lo, | 1107 file_token_lo, |
1125 file_token_hi, | 1108 file_token_hi, |
1126 out_handle, | 1109 out_handle, |
1127 out_file_path)); | 1110 out_file_path)); |
1128 } | 1111 } |
1129 | 1112 |
1130 #if defined(OS_WIN) | 1113 #if defined(OS_WIN) |
1131 void NaClProcessHost::OnAttachDebugExceptionHandler(const std::string& info, | 1114 void NaClProcessHost::OnAttachDebugExceptionHandler(const std::string& info, |
1132 IPC::Message* reply_msg) { | 1115 IPC::Message* reply_msg) { |
1133 CHECK(!uses_nonsfi_mode_); | 1116 CHECK(!uses_nonsfi_mode_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1194 process_handle.Take(), info, | 1177 process_handle.Take(), info, |
1195 base::MessageLoopProxy::current(), | 1178 base::MessageLoopProxy::current(), |
1196 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1179 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1197 weak_factory_.GetWeakPtr())); | 1180 weak_factory_.GetWeakPtr())); |
1198 return true; | 1181 return true; |
1199 } | 1182 } |
1200 } | 1183 } |
1201 #endif | 1184 #endif |
1202 | 1185 |
1203 } // namespace nacl | 1186 } // namespace nacl |
OLD | NEW |