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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 bool nonsfi_mode_enabled = | 467 bool nonsfi_mode_enabled = |
468 nonsfi_mode_forced_by_command_line || nonsfi_mode_allowed; | 468 nonsfi_mode_forced_by_command_line || nonsfi_mode_allowed; |
469 | 469 |
470 if (!nonsfi_mode_enabled) { | 470 if (!nonsfi_mode_enabled) { |
471 SendErrorToRenderer( | 471 SendErrorToRenderer( |
472 "NaCl non-SFI mode is not available for this platform" | 472 "NaCl non-SFI mode is not available for this platform" |
473 " and NaCl module."); | 473 " and NaCl module."); |
474 delete this; | 474 delete this; |
475 return; | 475 return; |
476 } | 476 } |
| 477 |
| 478 if (!enable_ppapi_proxy()) { |
| 479 SendErrorToRenderer( |
| 480 "PPAPI proxy must be enabled on NaCl in Non-SFI mode."); |
| 481 delete this; |
| 482 return; |
| 483 } |
477 } else { | 484 } else { |
478 // Rather than creating a socket pair in the renderer, and passing | 485 // Rather than creating a socket pair in the renderer, and passing |
479 // one side through the browser to sel_ldr, socket pairs are created | 486 // one side through the browser to sel_ldr, socket pairs are created |
480 // in the browser and then passed to the renderer and sel_ldr. | 487 // in the browser and then passed to the renderer and sel_ldr. |
481 // | 488 // |
482 // This is mainly for the benefit of Windows, where sockets cannot | 489 // This is mainly for the benefit of Windows, where sockets cannot |
483 // be passed in messages, but are copied via DuplicateHandle(). | 490 // be passed in messages, but are copied via DuplicateHandle(). |
484 // This means the sandboxed renderer cannot send handles to the | 491 // This means the sandboxed renderer cannot send handles to the |
485 // browser process. | 492 // browser process. |
486 | 493 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 } | 672 } |
666 #endif | 673 #endif |
667 process_->Launch( | 674 process_->Launch( |
668 new NaClSandboxedProcessLauncherDelegate(process_->GetHost()), | 675 new NaClSandboxedProcessLauncherDelegate(process_->GetHost()), |
669 cmd_line.release(), | 676 cmd_line.release(), |
670 true); | 677 true); |
671 return true; | 678 return true; |
672 } | 679 } |
673 | 680 |
674 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { | 681 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { |
675 bool handled = true; | |
676 if (uses_nonsfi_mode_) { | 682 if (uses_nonsfi_mode_) { |
677 // IPC messages relating to NaCl's validation cache must not be exposed | 683 // IPC messages relating to NaCl's validation cache must not be exposed |
678 // in Non-SFI Mode, otherwise a Non-SFI nexe could use | 684 // in Non-SFI Mode, otherwise a Non-SFI nexe could use SetKnownToValidate |
679 // SetKnownToValidate to create a hole in the SFI sandbox. | 685 // to create a hole in the SFI sandbox. |
680 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 686 // In Non-SFI mode, no message is expected. |
681 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 687 return false; |
682 OnPpapiChannelsCreated) | 688 } |
683 IPC_MESSAGE_UNHANDLED(handled = false) | 689 |
684 IPC_END_MESSAGE_MAP() | 690 bool handled = true; |
685 } else { | 691 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) |
686 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 692 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, |
687 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, | 693 OnQueryKnownToValidate) |
688 OnQueryKnownToValidate) | 694 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, |
689 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, | 695 OnSetKnownToValidate) |
690 OnSetKnownToValidate) | 696 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken, |
691 IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken, | 697 OnResolveFileToken) |
692 OnResolveFileToken) | |
693 | 698 |
694 #if defined(OS_WIN) | 699 #if defined(OS_WIN) |
695 IPC_MESSAGE_HANDLER_DELAY_REPLY( | 700 IPC_MESSAGE_HANDLER_DELAY_REPLY( |
696 NaClProcessMsg_AttachDebugExceptionHandler, | 701 NaClProcessMsg_AttachDebugExceptionHandler, |
697 OnAttachDebugExceptionHandler) | 702 OnAttachDebugExceptionHandler) |
698 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, | 703 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected, |
699 OnDebugStubPortSelected) | 704 OnDebugStubPortSelected) |
700 #endif | 705 #endif |
701 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, | 706 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated, |
702 OnPpapiChannelsCreated) | 707 OnPpapiChannelsCreated) |
703 IPC_MESSAGE_UNHANDLED(handled = false) | 708 IPC_MESSAGE_UNHANDLED(handled = false) |
704 IPC_END_MESSAGE_MAP() | 709 IPC_END_MESSAGE_MAP() |
705 } | |
706 return handled; | 710 return handled; |
707 } | 711 } |
708 | 712 |
709 void NaClProcessHost::OnProcessLaunched() { | 713 void NaClProcessHost::OnProcessLaunched() { |
710 if (!StartWithLaunchedProcess()) | 714 if (!StartWithLaunchedProcess()) |
711 delete this; | 715 delete this; |
712 } | 716 } |
713 | 717 |
714 // Called when the NaClBrowser singleton has been fully initialized. | 718 // Called when the NaClBrowser singleton has been fully initialized. |
715 void NaClProcessHost::OnResourcesReady() { | 719 void NaClProcessHost::OnResourcesReady() { |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 true /* is_executable */), | 972 true /* is_executable */), |
969 base::Bind(&NaClProcessHost::StartNaClFileResolved, | 973 base::Bind(&NaClProcessHost::StartNaClFileResolved, |
970 weak_factory_.GetWeakPtr(), | 974 weak_factory_.GetWeakPtr(), |
971 params, | 975 params, |
972 file_path))) { | 976 file_path))) { |
973 return true; | 977 return true; |
974 } | 978 } |
975 } | 979 } |
976 } | 980 } |
977 | 981 |
978 params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), | 982 StartNaClFileResolved(params, base::FilePath(), base::File()); |
979 process_->GetData().handle); | |
980 process_->Send(new NaClProcessMsg_Start(params)); | |
981 return true; | 983 return true; |
982 } | 984 } |
983 | 985 |
984 void NaClProcessHost::StartNaClFileResolved( | 986 void NaClProcessHost::StartNaClFileResolved( |
985 NaClStartParams params, | 987 NaClStartParams params, |
986 const base::FilePath& file_path, | 988 const base::FilePath& file_path, |
987 base::File checked_nexe_file) { | 989 base::File checked_nexe_file) { |
988 if (checked_nexe_file.IsValid()) { | 990 if (checked_nexe_file.IsValid()) { |
989 // Release the file received from the renderer. This has to be done on a | 991 // Release the file received from the renderer. This has to be done on a |
990 // thread where IO is permitted, though. | 992 // thread where IO is permitted, though. |
991 content::BrowserThread::GetBlockingPool()->PostTask( | 993 content::BrowserThread::GetBlockingPool()->PostTask( |
992 FROM_HERE, | 994 FROM_HERE, |
993 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); | 995 base::Bind(&CloseFile, base::Passed(nexe_file_.Pass()))); |
994 params.nexe_file_path_metadata = file_path; | 996 params.nexe_file_path_metadata = file_path; |
995 params.nexe_file = IPC::TakeFileHandleForProcess( | 997 params.nexe_file = IPC::TakeFileHandleForProcess( |
996 checked_nexe_file.Pass(), process_->GetData().handle); | 998 checked_nexe_file.Pass(), process_->GetData().handle); |
997 } else { | 999 } else { |
998 params.nexe_file = IPC::TakeFileHandleForProcess( | 1000 params.nexe_file = IPC::TakeFileHandleForProcess( |
999 nexe_file_.Pass(), process_->GetData().handle); | 1001 nexe_file_.Pass(), process_->GetData().handle); |
1000 } | 1002 } |
| 1003 |
| 1004 #if defined(OS_LINUX) |
| 1005 // In Non-SFI mode, create socket pairs for IPC channels here, unlike in |
| 1006 // SFI-mode, in which those channels are created in nacl_listener.cc. |
| 1007 // This is for security hardening. We can then prohibit the socketpair() |
| 1008 // system call in nacl_helper and nacl_helper_nonsfi. |
| 1009 if (uses_nonsfi_mode_) { |
| 1010 // Note: here, because some FDs/handles for the NaCl loader process are |
| 1011 // already opened, they are transferred to NaCl loader process even if |
| 1012 // an error occurs first. It is because this is the simplest way to |
| 1013 // ensure that these FDs/handles don't get leaked and that the NaCl loader |
| 1014 // process will exit properly. |
| 1015 bool has_error = false; |
| 1016 |
| 1017 // Note: this check is redundant. We check this earlier. |
| 1018 DCHECK(params.enable_ipc_proxy); |
| 1019 |
| 1020 ScopedChannelHandle ppapi_browser_server_channel_handle; |
| 1021 ScopedChannelHandle ppapi_browser_client_channel_handle; |
| 1022 ScopedChannelHandle ppapi_renderer_server_channel_handle; |
| 1023 ScopedChannelHandle ppapi_renderer_client_channel_handle; |
| 1024 ScopedChannelHandle trusted_service_server_channel_handle; |
| 1025 ScopedChannelHandle trusted_service_client_channel_handle; |
| 1026 ScopedChannelHandle manifest_service_server_channel_handle; |
| 1027 ScopedChannelHandle manifest_service_client_channel_handle; |
| 1028 |
| 1029 if (!CreateChannelHandlePair(&ppapi_browser_server_channel_handle, |
| 1030 &ppapi_browser_client_channel_handle) || |
| 1031 !CreateChannelHandlePair(&ppapi_renderer_server_channel_handle, |
| 1032 &ppapi_renderer_client_channel_handle) || |
| 1033 !CreateChannelHandlePair(&trusted_service_server_channel_handle, |
| 1034 &trusted_service_client_channel_handle) || |
| 1035 !CreateChannelHandlePair(&manifest_service_server_channel_handle, |
| 1036 &manifest_service_client_channel_handle)) { |
| 1037 SendErrorToRenderer("Failed to create socket pairs."); |
| 1038 has_error = true; |
| 1039 } |
| 1040 |
| 1041 if (!has_error && |
| 1042 !StartPPAPIProxy(ppapi_browser_client_channel_handle.Pass())) { |
| 1043 SendErrorToRenderer("Failed to start browser PPAPI proxy."); |
| 1044 has_error = true; |
| 1045 } |
| 1046 |
| 1047 if (!has_error) { |
| 1048 // On success, send back a success message to the renderer process, |
| 1049 // and transfer the channel handles for the NaCl loader process to |
| 1050 // |params|. |
| 1051 ReplyToRenderer(ppapi_renderer_client_channel_handle.Pass(), |
| 1052 trusted_service_client_channel_handle.Pass(), |
| 1053 manifest_service_client_channel_handle.Pass()); |
| 1054 params.ppapi_browser_channel_handle = |
| 1055 ppapi_browser_server_channel_handle.release(); |
| 1056 params.ppapi_renderer_channel_handle = |
| 1057 ppapi_renderer_server_channel_handle.release(); |
| 1058 params.trusted_service_channel_handle = |
| 1059 trusted_service_server_channel_handle.release(); |
| 1060 params.manifest_service_channel_handle = |
| 1061 manifest_service_server_channel_handle.release(); |
| 1062 } |
| 1063 } |
| 1064 #endif |
| 1065 |
1001 process_->Send(new NaClProcessMsg_Start(params)); | 1066 process_->Send(new NaClProcessMsg_Start(params)); |
1002 } | 1067 } |
1003 | 1068 |
1004 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 1069 #if defined(OS_LINUX) |
1005 // received. | 1070 // static |
1006 void NaClProcessHost::OnPpapiChannelsCreated( | 1071 bool NaClProcessHost::CreateChannelHandlePair( |
1007 const IPC::ChannelHandle& raw_browser_channel_handle, | 1072 ScopedChannelHandle* channel_handle1, |
1008 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, | 1073 ScopedChannelHandle* channel_handle2) { |
1009 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, | 1074 DCHECK(channel_handle1); |
1010 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { | 1075 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 | 1076 |
1019 if (!enable_ppapi_proxy()) { | 1077 int fd1 = -1; |
1020 ReplyToRenderer(ScopedChannelHandle(), | 1078 int fd2 = -1; |
1021 trusted_renderer_channel_handle.Pass(), | 1079 if (!IPC::SocketPair(&fd1, &fd2)) { |
1022 manifest_service_channel_handle.Pass()); | 1080 return false; |
1023 return; | |
1024 } | 1081 } |
1025 | 1082 |
| 1083 IPC::ChannelHandle handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
| 1084 handle.socket = base::FileDescriptor(fd1, true); |
| 1085 channel_handle1->reset(handle); |
| 1086 handle.socket = base::FileDescriptor(fd2, true); |
| 1087 channel_handle2->reset(handle); |
| 1088 return true; |
| 1089 } |
| 1090 #endif |
| 1091 |
| 1092 bool NaClProcessHost::StartPPAPIProxy(ScopedChannelHandle channel_handle) { |
1026 if (ipc_proxy_channel_.get()) { | 1093 if (ipc_proxy_channel_.get()) { |
1027 // Attempt to open more than 1 browser channel is not supported. | 1094 // Attempt to open more than 1 browser channel is not supported. |
1028 // Shut down the NaCl process. | 1095 // Shut down the NaCl process. |
1029 process_->GetHost()->ForceShutdown(); | 1096 process_->GetHost()->ForceShutdown(); |
1030 return; | 1097 return false; |
1031 } | 1098 } |
1032 | 1099 |
1033 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); | 1100 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); |
1034 | 1101 |
1035 ipc_proxy_channel_ = | 1102 ipc_proxy_channel_ = IPC::ChannelProxy::Create( |
1036 IPC::ChannelProxy::Create(browser_channel_handle.release(), | 1103 channel_handle.release(), |
1037 IPC::Channel::MODE_CLIENT, | 1104 IPC::Channel::MODE_CLIENT, |
1038 NULL, | 1105 NULL, |
1039 base::MessageLoopProxy::current().get()); | 1106 base::MessageLoopProxy::current().get()); |
1040 // Create the browser ppapi host and enable PPAPI message dispatching to the | 1107 // Create the browser ppapi host and enable PPAPI message dispatching to the |
1041 // browser process. | 1108 // browser process. |
1042 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( | 1109 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( |
1043 ipc_proxy_channel_.get(), // sender | 1110 ipc_proxy_channel_.get(), // sender |
1044 permissions_, | 1111 permissions_, |
1045 process_->GetData().handle, | 1112 process_->GetData().handle, |
1046 ipc_proxy_channel_.get(), | 1113 ipc_proxy_channel_.get(), |
1047 nacl_host_message_filter_->render_process_id(), | 1114 nacl_host_message_filter_->render_process_id(), |
1048 render_view_id_, | 1115 render_view_id_, |
1049 profile_directory_)); | 1116 profile_directory_)); |
(...skipping 19 matching lines...) Expand all Loading... |
1069 } | 1136 } |
1070 } | 1137 } |
1071 | 1138 |
1072 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( | 1139 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( |
1073 scoped_ptr<ppapi::host::HostFactory>( | 1140 scoped_ptr<ppapi::host::HostFactory>( |
1074 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( | 1141 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( |
1075 ppapi_host_.get()))); | 1142 ppapi_host_.get()))); |
1076 | 1143 |
1077 // Send a message to initialize the IPC dispatchers in the NaCl plugin. | 1144 // Send a message to initialize the IPC dispatchers in the NaCl plugin. |
1078 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); | 1145 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); |
| 1146 return true; |
| 1147 } |
| 1148 |
| 1149 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is |
| 1150 // received. |
| 1151 void NaClProcessHost::OnPpapiChannelsCreated( |
| 1152 const IPC::ChannelHandle& raw_ppapi_browser_channel_handle, |
| 1153 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, |
| 1154 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, |
| 1155 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { |
| 1156 ScopedChannelHandle ppapi_browser_channel_handle( |
| 1157 raw_ppapi_browser_channel_handle); |
| 1158 ScopedChannelHandle ppapi_renderer_channel_handle( |
| 1159 raw_ppapi_renderer_channel_handle); |
| 1160 ScopedChannelHandle trusted_renderer_channel_handle( |
| 1161 raw_trusted_renderer_channel_handle); |
| 1162 ScopedChannelHandle manifest_service_channel_handle( |
| 1163 raw_manifest_service_channel_handle); |
| 1164 |
| 1165 if (enable_ppapi_proxy()) { |
| 1166 if (!StartPPAPIProxy(ppapi_browser_channel_handle.Pass())) { |
| 1167 SendErrorToRenderer("Browser PPAPI proxy could not start."); |
| 1168 return; |
| 1169 } |
| 1170 } else { |
| 1171 // If PPAPI proxy is disabled, channel handles should be invalid. |
| 1172 DCHECK(ppapi_browser_channel_handle.get().name.empty()); |
| 1173 DCHECK(ppapi_renderer_channel_handle.get().name.empty()); |
| 1174 // Invalidate, just in case. |
| 1175 ppapi_browser_channel_handle.reset(); |
| 1176 ppapi_renderer_channel_handle.reset(); |
| 1177 } |
1079 | 1178 |
1080 // Let the renderer know that the IPC channels are established. | 1179 // Let the renderer know that the IPC channels are established. |
1081 ReplyToRenderer(ppapi_renderer_channel_handle.Pass(), | 1180 ReplyToRenderer(ppapi_renderer_channel_handle.Pass(), |
1082 trusted_renderer_channel_handle.Pass(), | 1181 trusted_renderer_channel_handle.Pass(), |
1083 manifest_service_channel_handle.Pass()); | 1182 manifest_service_channel_handle.Pass()); |
1084 } | 1183 } |
1085 | 1184 |
1086 bool NaClProcessHost::StartWithLaunchedProcess() { | 1185 bool NaClProcessHost::StartWithLaunchedProcess() { |
1087 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 1186 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
1088 | 1187 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1254 process.Pass(), info, | 1353 process.Pass(), info, |
1255 base::MessageLoopProxy::current(), | 1354 base::MessageLoopProxy::current(), |
1256 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1355 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1257 weak_factory_.GetWeakPtr())); | 1356 weak_factory_.GetWeakPtr())); |
1258 return true; | 1357 return true; |
1259 } | 1358 } |
1260 } | 1359 } |
1261 #endif | 1360 #endif |
1262 | 1361 |
1263 } // namespace nacl | 1362 } // namespace nacl |
OLD | NEW |