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