Chromium Code Reviews| 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 |