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 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 } | 665 } |
666 #endif | 666 #endif |
667 process_->Launch( | 667 process_->Launch( |
668 new NaClSandboxedProcessLauncherDelegate(process_->GetHost()), | 668 new NaClSandboxedProcessLauncherDelegate(process_->GetHost()), |
669 cmd_line.release(), | 669 cmd_line.release(), |
670 true); | 670 true); |
671 return true; | 671 return true; |
672 } | 672 } |
673 | 673 |
674 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { | 674 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { |
675 if (uses_nonsfi_mode_) { | |
676 // In Non-SFI mode, no message is expected. | |
677 return false; | |
678 } | |
679 | |
675 bool handled = true; | 680 bool handled = true; |
676 if (uses_nonsfi_mode_) { | 681 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) |
677 // IPC messages relating to NaCl's validation cache must not be exposed | 682 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, |
Mark Seaborn
2015/05/12 23:24:06
Please keep this comment, and add it after "// In
hidehiko
2015/05/13 06:39:20
Done.
| |
678 // in Non-SFI Mode, otherwise a Non-SFI nexe could use | 683 OnQueryKnownToValidate) |
679 // SetKnownToValidate to create a hole in the SFI sandbox. | 684 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, |
680 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 685 OnSetKnownToValidate) |
681 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 686 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken, |
682 OnPpapiChannelsCreated) | 687 OnResolveFileToken) |
683 IPC_MESSAGE_UNHANDLED(handled = false) | |
684 IPC_END_MESSAGE_MAP() | |
685 } else { | |
686 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | |
687 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, | |
688 OnQueryKnownToValidate) | |
689 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, | |
690 OnSetKnownToValidate) | |
691 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken, | |
692 OnResolveFileToken) | |
693 | 688 |
694 #if defined(OS_WIN) | 689 #if defined(OS_WIN) |
695 IPC_MESSAGE_HANDLER_DELAY_REPLY( | 690 IPC_MESSAGE_HANDLER_DELAY_REPLY( |
696 NaClProcessMsg_AttachDebugExceptionHandler, | 691 NaClProcessMsg_AttachDebugExceptionHandler, |
697 OnAttachDebugExceptionHandler) | 692 OnAttachDebugExceptionHandler) |
698 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, | 693 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, |
699 OnDebugStubPortSelected) | 694 OnDebugStubPortSelected) |
700 #endif | 695 #endif |
701 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 696 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, |
702 OnPpapiChannelsCreated) | 697 OnPpapiChannelsCreated) |
703 IPC_MESSAGE_UNHANDLED(handled = false) | 698 IPC_MESSAGE_UNHANDLED(handled = false) |
704 IPC_END_MESSAGE_MAP() | 699 IPC_END_MESSAGE_MAP() |
705 } | |
706 return handled; | 700 return handled; |
707 } | 701 } |
708 | 702 |
709 void NaClProcessHost::OnProcessLaunched() { | 703 void NaClProcessHost::OnProcessLaunched() { |
710 if (!StartWithLaunchedProcess()) | 704 if (!StartWithLaunchedProcess()) |
711 delete this; | 705 delete this; |
712 } | 706 } |
713 | 707 |
714 // Called when the NaClBrowser singleton has been fully initialized. | 708 // Called when the NaClBrowser singleton has been fully initialized. |
715 void NaClProcessHost::OnResourcesReady() { | 709 void NaClProcessHost::OnResourcesReady() { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
865 // Currently, non-SFI mode is supported only on Linux. | 859 // Currently, non-SFI mode is supported only on Linux. |
866 #if defined(OS_LINUX) | 860 #if defined(OS_LINUX) |
867 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is | 861 // In non-SFI mode, we do not use SRPC. Make sure that the socketpair is |
868 // not created. | 862 // not created. |
869 DCHECK(!socket_for_sel_ldr_.IsValid()); | 863 DCHECK(!socket_for_sel_ldr_.IsValid()); |
870 #endif | 864 #endif |
871 if (enable_nacl_debug) { | 865 if (enable_nacl_debug) { |
872 base::ProcessId pid = base::GetProcId(process_->GetData().handle); | 866 base::ProcessId pid = base::GetProcId(process_->GetData().handle); |
873 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; | 867 LOG(WARNING) << "nonsfi nacl plugin running in " << pid; |
874 } | 868 } |
869 | |
870 DCHECK(params.enable_ipc_proxy); | |
871 if (!params.enable_ipc_proxy) { | |
Mark Seaborn
2015/05/12 23:24:06
This is basically input validation of what the ren
hidehiko
2015/05/13 06:39:20
Done.
| |
872 LOG(ERROR) << "In Non-SFI mode, PPAPI proxy must be enabled."; | |
873 return false; | |
874 } | |
875 } else { | 875 } else { |
876 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 876 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
877 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 877 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
878 params.version = NaClBrowser::GetDelegate()->GetVersionString(); | 878 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
879 params.enable_debug_stub = enable_nacl_debug; | 879 params.enable_debug_stub = enable_nacl_debug; |
880 | 880 |
881 const ChildProcessData& data = process_->GetData(); | 881 const ChildProcessData& data = process_->GetData(); |
882 params.imc_bootstrap_handle = | 882 params.imc_bootstrap_handle = |
883 IPC::TakeFileHandleForProcess(socket_for_sel_ldr_.Pass(), data.handle); | 883 IPC::TakeFileHandleForProcess(socket_for_sel_ldr_.Pass(), data.handle); |
884 if (params.imc_bootstrap_handle == IPC::InvalidPlatformFileForTransit()) { | 884 if (params.imc_bootstrap_handle == IPC::InvalidPlatformFileForTransit()) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
968 true /* is_executable */), | 968 true /* is_executable */), |
969 base::Bind(&NaClProcessHost::StartNaClFileResolved, | 969 base::Bind(&NaClProcessHost::StartNaClFileResolved, |
970 weak_factory_.GetWeakPtr(), | 970 weak_factory_.GetWeakPtr(), |
971 params, | 971 params, |
972 file_path))) { | 972 file_path))) { |
973 return true; | 973 return true; |
974 } | 974 } |
975 } | 975 } |
976 } | 976 } |
977 | 977 |
978 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | 978 StartNaClFileResolved(params, base::FilePath(), base::File()); |
979 process_->GetData().handle); | |
980 process_->Send(new NaClProcessMsg_Start(params)); | |
981 return true; | 979 return true; |
982 } | 980 } |
983 | 981 |
984 void NaClProcessHost::StartNaClFileResolved( | 982 void NaClProcessHost::StartNaClFileResolved( |
985 NaClStartParams params, | 983 NaClStartParams params, |
986 const base::FilePath& file_path, | 984 const base::FilePath& file_path, |
987 base::File checked_nexe_file) { | 985 base::File checked_nexe_file) { |
988 if (checked_nexe_file.IsValid()) { | 986 if (checked_nexe_file.IsValid()) { |
989 // Release the file received from the renderer. This has to be done on a | 987 // Release the file received from the renderer. This has to be done on a |
990 // thread where IO is permitted, though. | 988 // thread where IO is permitted, though. |
991 content::BrowserThread::GetBlockingPool()->PostTask( | 989 content::BrowserThread::GetBlockingPool()->PostTask( |
992 FROM_HERE, | 990 FROM_HERE, |
993 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); | 991 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); |
994 params.nexe_file_path_metadata = file_path; | 992 params.nexe_file_path_metadata = file_path; |
995 params.nexe_file = IPC::TakeFileHandleForProcess( | 993 params.nexe_file = IPC::TakeFileHandleForProcess( |
996 checked_nexe_file.Pass(), process_->GetData().handle); | 994 checked_nexe_file.Pass(), process_->GetData().handle); |
997 } else { | 995 } else { |
998 params.nexe_file = IPC::TakeFileHandleForProcess( | 996 params.nexe_file = IPC::TakeFileHandleForProcess( |
999 nexe_file_.Pass(), process_->GetData().handle); | 997 nexe_file_.Pass(), process_->GetData().handle); |
1000 } | 998 } |
999 | |
1000 #if defined(OS_LINUX) | |
1001 // In Non-SFI mode, create socket pairs for IPC channels, here, unlike in | |
Mark Seaborn
2015/05/12 23:24:06
Grammar nit: could remove comma before "here"
hidehiko
2015/05/13 06:39:20
Done.
| |
1002 // SFI-mode, in which those channels are created in nacl_listener.cc. | |
1003 // This is for security hardening. We can then prohibit the socketpair() | |
1004 // system call in nacl_helper and nacl_helper_nonsfi. | |
1005 if (uses_nonsfi_mode_) { | |
1006 // Note: here, because some resources for the plugin process are already | |
Mark Seaborn
2015/05/12 23:24:06
Nit: "plugin process" -> "NaCl loader process", x2
hidehiko
2015/05/13 06:39:20
Done.
| |
1007 // opened, they must be sent to plugin process because these cannot be | |
Mark Seaborn
2015/05/12 23:24:06
"cannot be closed in this process" could be mislea
hidehiko
2015/05/13 06:39:20
Done.
| |
1008 // closed in this process properly. | |
1009 bool has_error = false; | |
1010 | |
1011 // The case this condition is not satisfied should be handled in | |
Mark Seaborn
2015/05/12 23:24:06
Nit: "The case where this condition..." perhaps?
hidehiko
2015/05/13 06:39:20
Done.
| |
1012 // StartNaClExecution(). | |
1013 DCHECK(params.enable_ipc_proxy); | |
1014 | |
1015 ScopedChannelHandle ppapi_browser_server_channel_handle; | |
Mark Seaborn
2015/05/12 23:24:06
I wonder if it would it be worth doing:
typedef s
hidehiko
2015/05/13 06:39:20
I do not want to introduce such a pair. Indeed it
| |
1016 ScopedChannelHandle ppapi_browser_client_channel_handle; | |
1017 ScopedChannelHandle ppapi_renderer_server_channel_handle; | |
1018 ScopedChannelHandle ppapi_renderer_client_channel_handle; | |
1019 ScopedChannelHandle trusted_service_server_channel_handle; | |
1020 ScopedChannelHandle trusted_service_client_channel_handle; | |
1021 ScopedChannelHandle manifest_service_server_channel_handle; | |
1022 ScopedChannelHandle manifest_service_client_channel_handle; | |
1023 | |
1024 if (!CreateChannelHandlePair(&ppapi_browser_server_channel_handle, | |
1025 &ppapi_browser_client_channel_handle) || | |
1026 !CreateChannelHandlePair(&ppapi_renderer_server_channel_handle, | |
1027 &ppapi_renderer_client_channel_handle) || | |
1028 !CreateChannelHandlePair(&trusted_service_server_channel_handle, | |
1029 &trusted_service_client_channel_handle) || | |
1030 !CreateChannelHandlePair(&manifest_service_server_channel_handle, | |
1031 &manifest_service_client_channel_handle)) { | |
1032 SendErrorToRenderer("Failed to create socket pairs."); | |
1033 has_error = true; | |
1034 } | |
1035 | |
1036 if (!has_error && | |
1037 !StartPPAPIProxy(ppapi_browser_client_channel_handle.Pass())) { | |
1038 SendErrorToRenderer("Failed to start browser PPAPI proxy."); | |
1039 has_error = true; | |
1040 } | |
1041 | |
1042 if (!has_error) { | |
1043 // On success, send back a success message to the renderer process, | |
1044 // and, transfer the channel handles for the plugin process to |params|. | |
Mark Seaborn
2015/05/12 23:24:06
Nit: remove comma after "and"
Also "plugin proces
hidehiko
2015/05/13 06:39:20
Done.
| |
1045 ReplyToRenderer(ppapi_renderer_client_channel_handle.Pass(), | |
1046 trusted_service_client_channel_handle.Pass(), | |
1047 manifest_service_client_channel_handle.Pass()); | |
1048 params.ppapi_browser_channel_handle = | |
1049 ppapi_browser_server_channel_handle.release(); | |
1050 params.ppapi_renderer_channel_handle = | |
1051 ppapi_renderer_server_channel_handle.release(); | |
1052 params.trusted_service_channel_handle = | |
1053 trusted_service_server_channel_handle.release(); | |
1054 params.manifest_service_channel_handle = | |
1055 manifest_service_server_channel_handle.release(); | |
1056 } | |
1057 } | |
1058 #endif | |
1059 | |
1001 process_->Send(new NaClProcessMsg_Start(params)); | 1060 process_->Send(new NaClProcessMsg_Start(params)); |
1002 } | 1061 } |
1003 | 1062 |
1004 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 1063 #if defined(OS_LINUX) |
1005 // received. | 1064 // static |
1006 void NaClProcessHost::OnPpapiChannelsCreated( | 1065 bool NaClProcessHost::CreateChannelHandlePair( |
1007 const IPC::ChannelHandle& raw_browser_channel_handle, | 1066 ScopedChannelHandle* channel_handle1, |
1008 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, | 1067 ScopedChannelHandle* channel_handle2) { |
1009 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, | 1068 DCHECK(channel_handle1); |
1010 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { | 1069 DCHECK(channel_handle2); |
1011 ScopedChannelHandle browser_channel_handle(raw_browser_channel_handle); | |
1012 ScopedChannelHandle ppapi_renderer_channel_handle( | |
1013 raw_ppapi_renderer_channel_handle); | |
1014 ScopedChannelHandle trusted_renderer_channel_handle( | |
1015 raw_trusted_renderer_channel_handle); | |
1016 ScopedChannelHandle manifest_service_channel_handle( | |
1017 raw_manifest_service_channel_handle); | |
1018 | 1070 |
1019 if (!enable_ppapi_proxy()) { | 1071 int fd1 = -1; |
1020 ReplyToRenderer(ScopedChannelHandle(), | 1072 int fd2 = -1; |
1021 trusted_renderer_channel_handle.Pass(), | 1073 if (!IPC::SocketPair(&fd1, &fd2)) { |
1022 manifest_service_channel_handle.Pass()); | 1074 return false; |
1023 return; | |
1024 } | 1075 } |
1025 | 1076 |
1077 IPC::ChannelHandle handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
1078 handle.socket = base::FileDescriptor(fd1, true); | |
1079 channel_handle1->reset(handle); | |
1080 handle.socket = base::FileDescriptor(fd2, true); | |
1081 channel_handle2->reset(handle); | |
1082 return true; | |
1083 } | |
1084 #endif | |
1085 | |
1086 bool NaClProcessHost::StartPPAPIProxy(ScopedChannelHandle channel_handle) { | |
1026 if (ipc_proxy_channel_.get()) { | 1087 if (ipc_proxy_channel_.get()) { |
1027 // Attempt to open more than 1 browser channel is not supported. | 1088 // Attempt to open more than 1 browser channel is not supported. |
1028 // Shut down the NaCl process. | 1089 // Shut down the NaCl process. |
1029 process_->GetHost()->ForceShutdown(); | 1090 process_->GetHost()->ForceShutdown(); |
1030 return; | 1091 return false; |
1031 } | 1092 } |
1032 | 1093 |
1033 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); | 1094 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); |
1034 | 1095 |
1035 ipc_proxy_channel_ = | 1096 ipc_proxy_channel_ = IPC::ChannelProxy::Create( |
1036 IPC::ChannelProxy::Create(browser_channel_handle.release(), | 1097 channel_handle.release(), |
1037 IPC::Channel::MODE_CLIENT, | 1098 IPC::Channel::MODE_CLIENT, |
1038 NULL, | 1099 NULL, |
1039 base::MessageLoopProxy::current().get()); | 1100 base::MessageLoopProxy::current().get()); |
1040 // Create the browser ppapi host and enable PPAPI message dispatching to the | 1101 // Create the browser ppapi host and enable PPAPI message dispatching to the |
1041 // browser process. | 1102 // browser process. |
1042 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( | 1103 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( |
1043 ipc_proxy_channel_.get(), // sender | 1104 ipc_proxy_channel_.get(), // sender |
1044 permissions_, | 1105 permissions_, |
1045 process_->GetData().handle, | 1106 process_->GetData().handle, |
1046 ipc_proxy_channel_.get(), | 1107 ipc_proxy_channel_.get(), |
1047 nacl_host_message_filter_->render_process_id(), | 1108 nacl_host_message_filter_->render_process_id(), |
1048 render_view_id_, | 1109 render_view_id_, |
1049 profile_directory_)); | 1110 profile_directory_)); |
(...skipping 19 matching lines...) Expand all Loading... | |
1069 } | 1130 } |
1070 } | 1131 } |
1071 | 1132 |
1072 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( | 1133 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( |
1073 scoped_ptr<ppapi::host::HostFactory>( | 1134 scoped_ptr<ppapi::host::HostFactory>( |
1074 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( | 1135 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( |
1075 ppapi_host_.get()))); | 1136 ppapi_host_.get()))); |
1076 | 1137 |
1077 // Send a message to initialize the IPC dispatchers in the NaCl plugin. | 1138 // Send a message to initialize the IPC dispatchers in the NaCl plugin. |
1078 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); | 1139 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); |
1140 return true; | |
1141 } | |
1142 | |
1143 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | |
1144 // received. | |
1145 void NaClProcessHost::OnPpapiChannelsCreated( | |
1146 const IPC::ChannelHandle& raw_ppapi_browser_channel_handle, | |
1147 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, | |
1148 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, | |
1149 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { | |
1150 ScopedChannelHandle ppapi_browser_channel_handle( | |
1151 raw_ppapi_browser_channel_handle); | |
1152 ScopedChannelHandle ppapi_renderer_channel_handle( | |
1153 raw_ppapi_renderer_channel_handle); | |
1154 ScopedChannelHandle trusted_renderer_channel_handle( | |
1155 raw_trusted_renderer_channel_handle); | |
1156 ScopedChannelHandle manifest_service_channel_handle( | |
1157 raw_manifest_service_channel_handle); | |
1158 | |
1159 if (enable_ppapi_proxy()) { | |
1160 if (!StartPPAPIProxy(ppapi_browser_channel_handle.Pass())) { | |
1161 SendErrorToRenderer("Browser PPAPI proxy could not start."); | |
1162 return; | |
1163 } | |
1164 } else { | |
1165 // If PPAPI proxy is disabled, channel handles should be invalid. | |
1166 DCHECK(ppapi_browser_channel_handle.get().name.empty()); | |
1167 DCHECK(ppapi_renderer_channel_handle.get().name.empty()); | |
1168 // Invalidate, just in case. | |
1169 ppapi_browser_channel_handle.reset(); | |
1170 ppapi_renderer_channel_handle.reset(); | |
1171 } | |
1079 | 1172 |
1080 // Let the renderer know that the IPC channels are established. | 1173 // Let the renderer know that the IPC channels are established. |
1081 ReplyToRenderer(ppapi_renderer_channel_handle.Pass(), | 1174 ReplyToRenderer(ppapi_renderer_channel_handle.Pass(), |
1082 trusted_renderer_channel_handle.Pass(), | 1175 trusted_renderer_channel_handle.Pass(), |
1083 manifest_service_channel_handle.Pass()); | 1176 manifest_service_channel_handle.Pass()); |
1084 } | 1177 } |
1085 | 1178 |
1086 bool NaClProcessHost::StartWithLaunchedProcess() { | 1179 bool NaClProcessHost::StartWithLaunchedProcess() { |
1087 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 1180 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
1088 | 1181 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1254 process.Pass(), info, | 1347 process.Pass(), info, |
1255 base::MessageLoopProxy::current(), | 1348 base::MessageLoopProxy::current(), |
1256 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1349 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1257 weak_factory_.GetWeakPtr())); | 1350 weak_factory_.GetWeakPtr())); |
1258 return true; | 1351 return true; |
1259 } | 1352 } |
1260 } | 1353 } |
1261 #endif | 1354 #endif |
1262 | 1355 |
1263 } // namespace nacl | 1356 } // namespace nacl |
OLD | NEW |