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 <string.h> | 7 #include <string.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 | 204 |
205 void CloseFile(base::File file) { | 205 void CloseFile(base::File file) { |
206 // The base::File destructor will close the file for us. | 206 // The base::File destructor will close the file for us. |
207 } | 207 } |
208 | 208 |
209 } // namespace | 209 } // namespace |
210 | 210 |
211 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 211 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
212 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 212 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
213 | 213 |
214 // Unfortunately, we cannot use ScopedGeneric directly for IPC::ChannelHandle, | |
215 // because there is neither operator== nor operator != definition for it. | |
216 // Instead, define a simple wrapper for IPC::ChannelHandle with an assumption | |
217 // that this only takes a transferred IPC::ChannelHandle or one to be | |
218 // transferred via IPC. | |
219 class NaClProcessHost::ScopedChannelHandle { | |
220 public: | |
221 ScopedChannelHandle() { | |
222 } | |
223 explicit ScopedChannelHandle(const IPC::ChannelHandle& handle) | |
224 : handle_(handle) { | |
225 DCHECK(IsSupportedHandle(handle_)); | |
226 } | |
227 ScopedChannelHandle(ScopedChannelHandle&& other) : handle_(other.handle_) { | |
228 other.handle_ = IPC::ChannelHandle(); | |
229 DCHECK(IsSupportedHandle(handle_)); | |
230 } | |
231 ~ScopedChannelHandle() { | |
232 CloseIfNecessary(); | |
233 } | |
234 | |
235 const IPC::ChannelHandle& get() const { return handle_; } | |
236 IPC::ChannelHandle release() WARN_UNUSED_RESULT { | |
237 IPC::ChannelHandle result = handle_; | |
238 handle_ = IPC::ChannelHandle(); | |
239 return result; | |
240 } | |
241 | |
242 void reset(const IPC::ChannelHandle& handle = IPC::ChannelHandle()) { | |
243 DCHECK(IsSupportedHandle(handle)); | |
244 #if defined(OS_POSIX) | |
245 // Following the manner of base::ScopedGeneric, we do not support | |
246 // reset() with same handle for simplicity of the implementation. | |
247 CHECK(handle.socket.fd == -1 || handle.socket.fd != handle_.socket.fd); | |
248 #endif | |
249 CloseIfNecessary(); | |
250 handle_ = handle; | |
251 } | |
252 | |
253 private: | |
254 // Returns true if the given handle is closable automatically by this | |
255 // class. This function is just a helper for validation. | |
256 static bool IsSupportedHandle(const IPC::ChannelHandle& handle) { | |
257 #if defined(OS_WIN) | |
258 // On Windows, it is not supported to marshal the |pipe.handle|. | |
259 // In our case, we wrap a transferred ChannelHandle (or one to be | |
260 // transferred) via IPC, so we can assume |handle.pipe.handle| is NULL. | |
261 return handle.pipe.handle == NULL; | |
262 #else | |
263 return true; | |
264 #endif | |
265 } | |
266 | |
267 void CloseIfNecessary() { | |
268 #if defined(OS_POSIX) | |
269 if (handle_.socket.auto_close) { | |
270 // Defer closing task to the ScopedFD. | |
271 base::ScopedFD(handle_.socket.fd); | |
272 } | |
273 #endif | |
274 } | |
275 | |
276 IPC::ChannelHandle handle_; | |
277 | |
278 DISALLOW_COPY_AND_ASSIGN(ScopedChannelHandle); | |
279 }; | |
280 | |
281 NaClProcessHost::NaClProcessHost( | 214 NaClProcessHost::NaClProcessHost( |
282 const GURL& manifest_url, | 215 const GURL& manifest_url, |
283 base::File nexe_file, | 216 base::File nexe_file, |
284 const NaClFileToken& nexe_token, | 217 const NaClFileToken& nexe_token, |
285 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, | 218 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, |
286 ppapi::PpapiPermissions permissions, | 219 ppapi::PpapiPermissions permissions, |
287 int render_view_id, | 220 int render_view_id, |
288 uint32_t permission_bits, | 221 uint32_t permission_bits, |
289 bool uses_nonsfi_mode, | 222 bool uses_nonsfi_mode, |
290 bool off_the_record, | 223 bool off_the_record, |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
714 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 647 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
715 if (!nacl_browser->IsReady()) { | 648 if (!nacl_browser->IsReady()) { |
716 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); | 649 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); |
717 delete this; | 650 delete this; |
718 } else if (!StartNaClExecution()) { | 651 } else if (!StartNaClExecution()) { |
719 delete this; | 652 delete this; |
720 } | 653 } |
721 } | 654 } |
722 | 655 |
723 void NaClProcessHost::ReplyToRenderer( | 656 void NaClProcessHost::ReplyToRenderer( |
724 ScopedChannelHandle ppapi_channel_handle, | 657 mojo::ScopedMessagePipeHandle ppapi_channel_handle, |
725 ScopedChannelHandle trusted_channel_handle, | 658 mojo::ScopedMessagePipeHandle trusted_channel_handle, |
726 ScopedChannelHandle manifest_service_channel_handle) { | 659 mojo::ScopedMessagePipeHandle manifest_service_channel_handle) { |
727 // Hereafter, we always send an IPC message with handles created above | 660 // Hereafter, we always send an IPC message with handles created above |
728 // which, on Windows, are not closable in this process. | 661 // which, on Windows, are not closable in this process. |
729 std::string error_message; | 662 std::string error_message; |
730 base::SharedMemoryHandle crash_info_shmem_renderer_handle; | 663 base::SharedMemoryHandle crash_info_shmem_renderer_handle; |
731 if (!crash_info_shmem_.ShareToProcess(nacl_host_message_filter_->PeerHandle(), | 664 if (!crash_info_shmem_.ShareToProcess(nacl_host_message_filter_->PeerHandle(), |
732 &crash_info_shmem_renderer_handle)) { | 665 &crash_info_shmem_renderer_handle)) { |
733 // On error, we do not send "IPC::ChannelHandle"s to the renderer process. | 666 // On error, we do not send "IPC::ChannelHandle"s to the renderer process. |
734 // Note that some other FDs/handles still get sent to the renderer, but | 667 // Note that some other FDs/handles still get sent to the renderer, but |
735 // will be closed there. | 668 // will be closed there. |
736 ppapi_channel_handle.reset(); | 669 ppapi_channel_handle.reset(); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
961 } else { | 894 } else { |
962 params.nexe_file = IPC::TakePlatformFileForTransit(std::move(nexe_file_)); | 895 params.nexe_file = IPC::TakePlatformFileForTransit(std::move(nexe_file_)); |
963 } | 896 } |
964 | 897 |
965 #if defined(OS_LINUX) | 898 #if defined(OS_LINUX) |
966 // In Non-SFI mode, create socket pairs for IPC channels here, unlike in | 899 // In Non-SFI mode, create socket pairs for IPC channels here, unlike in |
967 // SFI-mode, in which those channels are created in nacl_listener.cc. | 900 // SFI-mode, in which those channels are created in nacl_listener.cc. |
968 // This is for security hardening. We can then prohibit the socketpair() | 901 // This is for security hardening. We can then prohibit the socketpair() |
969 // system call in nacl_helper and nacl_helper_nonsfi. | 902 // system call in nacl_helper and nacl_helper_nonsfi. |
970 if (uses_nonsfi_mode_) { | 903 if (uses_nonsfi_mode_) { |
971 // Note: here, because some FDs/handles for the NaCl loader process are | 904 // Note: here, because some FDs/handles for the NaCl loader process are |
Mark Seaborn
2016/10/17 21:28:26
I think you can remove this comment, since you rem
Sam McNally
2016/10/17 23:01:17
Done.
| |
972 // already opened, they are transferred to NaCl loader process even if | 905 // already opened, they are transferred to NaCl loader process even if |
973 // an error occurs first. It is because this is the simplest way to | 906 // an error occurs first. It is because this is the simplest way to |
974 // ensure that these FDs/handles don't get leaked and that the NaCl loader | 907 // ensure that these FDs/handles don't get leaked and that the NaCl loader |
975 // process will exit properly. | 908 // process will exit properly. |
976 bool has_error = false; | |
977 | 909 |
978 ScopedChannelHandle ppapi_browser_server_channel_handle; | 910 mojo::MessagePipe ppapi_browser_channel; |
979 ScopedChannelHandle ppapi_browser_client_channel_handle; | 911 mojo::MessagePipe ppapi_renderer_channel; |
980 ScopedChannelHandle ppapi_renderer_server_channel_handle; | 912 mojo::MessagePipe trusted_service_channel; |
981 ScopedChannelHandle ppapi_renderer_client_channel_handle; | 913 mojo::MessagePipe manifest_service_channel; |
982 ScopedChannelHandle trusted_service_server_channel_handle; | |
983 ScopedChannelHandle trusted_service_client_channel_handle; | |
984 ScopedChannelHandle manifest_service_server_channel_handle; | |
985 ScopedChannelHandle manifest_service_client_channel_handle; | |
986 | 914 |
987 if (!CreateChannelHandlePair(&ppapi_browser_server_channel_handle, | 915 if (!StartPPAPIProxy(std::move(ppapi_browser_channel.handle1))) { |
988 &ppapi_browser_client_channel_handle) || | 916 SendErrorToRenderer("Failed to start browser PPAPI proxy."); |
989 !CreateChannelHandlePair(&ppapi_renderer_server_channel_handle, | 917 return; |
990 &ppapi_renderer_client_channel_handle) || | |
991 !CreateChannelHandlePair(&trusted_service_server_channel_handle, | |
992 &trusted_service_client_channel_handle) || | |
993 !CreateChannelHandlePair(&manifest_service_server_channel_handle, | |
994 &manifest_service_client_channel_handle)) { | |
995 SendErrorToRenderer("Failed to create socket pairs."); | |
996 has_error = true; | |
997 } | 918 } |
998 | 919 |
999 if (!has_error && | 920 // On success, send back a success message to the renderer process, |
1000 !StartPPAPIProxy(std::move(ppapi_browser_client_channel_handle))) { | 921 // and transfer the channel handles for the NaCl loader process to |
1001 SendErrorToRenderer("Failed to start browser PPAPI proxy."); | 922 // |params|. |
1002 has_error = true; | 923 ReplyToRenderer(std::move(ppapi_renderer_channel.handle1), |
1003 } | 924 std::move(trusted_service_channel.handle1), |
1004 | 925 std::move(manifest_service_channel.handle1)); |
1005 if (!has_error) { | 926 params.ppapi_browser_channel_handle = |
1006 // On success, send back a success message to the renderer process, | 927 ppapi_browser_channel.handle0.release(); |
1007 // and transfer the channel handles for the NaCl loader process to | 928 params.ppapi_renderer_channel_handle = |
1008 // |params|. | 929 ppapi_renderer_channel.handle0.release(); |
1009 ReplyToRenderer(std::move(ppapi_renderer_client_channel_handle), | 930 params.trusted_service_channel_handle = |
1010 std::move(trusted_service_client_channel_handle), | 931 trusted_service_channel.handle0.release(); |
1011 std::move(manifest_service_client_channel_handle)); | 932 params.manifest_service_channel_handle = |
1012 params.ppapi_browser_channel_handle = | 933 manifest_service_channel.handle0.release(); |
1013 ppapi_browser_server_channel_handle.release(); | |
1014 params.ppapi_renderer_channel_handle = | |
1015 ppapi_renderer_server_channel_handle.release(); | |
1016 params.trusted_service_channel_handle = | |
1017 trusted_service_server_channel_handle.release(); | |
1018 params.manifest_service_channel_handle = | |
1019 manifest_service_server_channel_handle.release(); | |
1020 } | |
1021 } | 934 } |
1022 #endif | 935 #endif |
1023 | 936 |
1024 process_->Send(new NaClProcessMsg_Start(params)); | 937 process_->Send(new NaClProcessMsg_Start(params)); |
1025 } | 938 } |
1026 | 939 |
1027 #if defined(OS_LINUX) | 940 bool NaClProcessHost::StartPPAPIProxy( |
1028 // static | 941 mojo::ScopedMessagePipeHandle channel_handle) { |
1029 bool NaClProcessHost::CreateChannelHandlePair( | |
1030 ScopedChannelHandle* channel_handle1, | |
1031 ScopedChannelHandle* channel_handle2) { | |
1032 DCHECK(channel_handle1); | |
1033 DCHECK(channel_handle2); | |
1034 | |
1035 int fd1 = -1; | |
1036 int fd2 = -1; | |
1037 if (!IPC::SocketPair(&fd1, &fd2)) { | |
1038 return false; | |
1039 } | |
1040 | |
1041 IPC::ChannelHandle handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
1042 handle.socket = base::FileDescriptor(fd1, true); | |
1043 channel_handle1->reset(handle); | |
1044 handle.socket = base::FileDescriptor(fd2, true); | |
1045 channel_handle2->reset(handle); | |
1046 return true; | |
1047 } | |
1048 #endif | |
1049 | |
1050 bool NaClProcessHost::StartPPAPIProxy(ScopedChannelHandle channel_handle) { | |
1051 if (ipc_proxy_channel_.get()) { | 942 if (ipc_proxy_channel_.get()) { |
1052 // Attempt to open more than 1 browser channel is not supported. | 943 // Attempt to open more than 1 browser channel is not supported. |
1053 // Shut down the NaCl process. | 944 // Shut down the NaCl process. |
1054 process_->GetHost()->ForceShutdown(); | 945 process_->GetHost()->ForceShutdown(); |
1055 return false; | 946 return false; |
1056 } | 947 } |
1057 | 948 |
1058 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); | 949 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); |
1059 | 950 |
1060 ipc_proxy_channel_ = IPC::ChannelProxy::Create( | 951 ipc_proxy_channel_ = IPC::ChannelProxy::Create( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1102 return true; | 993 return true; |
1103 } | 994 } |
1104 | 995 |
1105 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 996 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is |
1106 // received. | 997 // received. |
1107 void NaClProcessHost::OnPpapiChannelsCreated( | 998 void NaClProcessHost::OnPpapiChannelsCreated( |
1108 const IPC::ChannelHandle& raw_ppapi_browser_channel_handle, | 999 const IPC::ChannelHandle& raw_ppapi_browser_channel_handle, |
1109 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, | 1000 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, |
1110 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, | 1001 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, |
1111 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { | 1002 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { |
1112 ScopedChannelHandle ppapi_browser_channel_handle( | 1003 DCHECK(raw_ppapi_browser_channel_handle.is_mojo_channel_handle()); |
1113 raw_ppapi_browser_channel_handle); | 1004 DCHECK(raw_ppapi_renderer_channel_handle.is_mojo_channel_handle()); |
1114 ScopedChannelHandle ppapi_renderer_channel_handle( | 1005 DCHECK(raw_trusted_renderer_channel_handle.is_mojo_channel_handle()); |
1115 raw_ppapi_renderer_channel_handle); | 1006 DCHECK(raw_manifest_service_channel_handle.is_mojo_channel_handle()); |
1116 ScopedChannelHandle trusted_renderer_channel_handle( | 1007 |
1117 raw_trusted_renderer_channel_handle); | 1008 mojo::ScopedMessagePipeHandle ppapi_browser_channel_handle( |
1118 ScopedChannelHandle manifest_service_channel_handle( | 1009 raw_ppapi_browser_channel_handle.mojo_handle); |
1119 raw_manifest_service_channel_handle); | 1010 mojo::ScopedMessagePipeHandle ppapi_renderer_channel_handle( |
1011 raw_ppapi_renderer_channel_handle.mojo_handle); | |
1012 mojo::ScopedMessagePipeHandle trusted_renderer_channel_handle( | |
1013 raw_trusted_renderer_channel_handle.mojo_handle); | |
1014 mojo::ScopedMessagePipeHandle manifest_service_channel_handle( | |
1015 raw_manifest_service_channel_handle.mojo_handle); | |
1120 | 1016 |
1121 if (!StartPPAPIProxy(std::move(ppapi_browser_channel_handle))) { | 1017 if (!StartPPAPIProxy(std::move(ppapi_browser_channel_handle))) { |
1122 SendErrorToRenderer("Browser PPAPI proxy could not start."); | 1018 SendErrorToRenderer("Browser PPAPI proxy could not start."); |
1123 return; | 1019 return; |
1124 } | 1020 } |
1125 | 1021 |
1126 // Let the renderer know that the IPC channels are established. | 1022 // Let the renderer know that the IPC channels are established. |
1127 ReplyToRenderer(std::move(ppapi_renderer_channel_handle), | 1023 ReplyToRenderer(std::move(ppapi_renderer_channel_handle), |
1128 std::move(trusted_renderer_channel_handle), | 1024 std::move(trusted_renderer_channel_handle), |
1129 std::move(manifest_service_channel_handle)); | 1025 std::move(manifest_service_channel_handle)); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1297 NaClStartDebugExceptionHandlerThread( | 1193 NaClStartDebugExceptionHandlerThread( |
1298 std::move(process), info, base::ThreadTaskRunnerHandle::Get(), | 1194 std::move(process), info, base::ThreadTaskRunnerHandle::Get(), |
1299 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1195 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1300 weak_factory_.GetWeakPtr())); | 1196 weak_factory_.GetWeakPtr())); |
1301 return true; | 1197 return true; |
1302 } | 1198 } |
1303 } | 1199 } |
1304 #endif | 1200 #endif |
1305 | 1201 |
1306 } // namespace nacl | 1202 } // namespace nacl |
OLD | NEW |