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 "chrome/browser/nacl_host/nacl_process_host.h" | 5 #include "chrome/browser/nacl_host/nacl_process_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // Only allow NaCl plugins to request certain permissions. We don't want | 120 // Only allow NaCl plugins to request certain permissions. We don't want |
121 // a compromised renderer to be able to start a nacl plugin with e.g. Flash | 121 // a compromised renderer to be able to start a nacl plugin with e.g. Flash |
122 // permissions which may expand the surface area of the sandbox. | 122 // permissions which may expand the surface area of the sandbox. |
123 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; | 123 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; |
124 return ppapi::PpapiPermissions::GetForCommandLine(masked_bits); | 124 return ppapi::PpapiPermissions::GetForCommandLine(masked_bits); |
125 } | 125 } |
126 | 126 |
127 } // namespace | 127 } // namespace |
128 | 128 |
129 struct NaClProcessHost::NaClInternal { | 129 struct NaClProcessHost::NaClInternal { |
130 std::vector<nacl::Handle> sockets_for_renderer; | 130 nacl::Handle socket_for_renderer; |
131 std::vector<nacl::Handle> sockets_for_sel_ldr; | 131 nacl::Handle socket_for_sel_ldr; |
| 132 |
| 133 NaClInternal() |
| 134 : socket_for_renderer(nacl::kInvalidHandle), |
| 135 socket_for_sel_ldr(nacl::kInvalidHandle) { } |
132 }; | 136 }; |
133 | 137 |
134 // ----------------------------------------------------------------------------- | 138 // ----------------------------------------------------------------------------- |
135 | 139 |
136 NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host) | 140 NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host) |
137 : host_(host) { | 141 : host_(host) { |
138 } | 142 } |
139 | 143 |
140 bool NaClProcessHost::PluginListener::OnMessageReceived( | 144 bool NaClProcessHost::PluginListener::OnMessageReceived( |
141 const IPC::Message& msg) { | 145 const IPC::Message& msg) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 process_->GetTerminationStatus(&exit_code); | 201 process_->GetTerminationStatus(&exit_code); |
198 std::string message = | 202 std::string message = |
199 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 203 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
200 exit_code, exit_code); | 204 exit_code, exit_code); |
201 if (exit_code == 0) { | 205 if (exit_code == 0) { |
202 LOG(INFO) << message; | 206 LOG(INFO) << message; |
203 } else { | 207 } else { |
204 LOG(ERROR) << message; | 208 LOG(ERROR) << message; |
205 } | 209 } |
206 | 210 |
207 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | 211 if (internal_->socket_for_renderer != nacl::kInvalidHandle) { |
208 if (nacl::Close(internal_->sockets_for_renderer[i]) != 0) { | 212 if (nacl::Close(internal_->socket_for_renderer) != 0) { |
209 NOTREACHED() << "nacl::Close() failed"; | 213 NOTREACHED() << "nacl::Close() failed"; |
210 } | 214 } |
211 } | 215 } |
212 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 216 |
213 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { | 217 if (internal_->socket_for_sel_ldr != nacl::kInvalidHandle) { |
| 218 if (nacl::Close(internal_->socket_for_sel_ldr) != 0) { |
214 NOTREACHED() << "nacl::Close() failed"; | 219 NOTREACHED() << "nacl::Close() failed"; |
215 } | 220 } |
216 } | 221 } |
217 | 222 |
218 if (reply_msg_) { | 223 if (reply_msg_) { |
219 // The process failed to launch for some reason. | 224 // The process failed to launch for some reason. |
220 // Don't keep the renderer hanging. | 225 // Don't keep the renderer hanging. |
221 reply_msg_->set_reply_error(); | 226 reply_msg_->set_reply_error(); |
222 chrome_render_message_filter_->Send(reply_msg_); | 227 chrome_render_message_filter_->Send(reply_msg_); |
223 } | 228 } |
(...skipping 21 matching lines...) Expand all Loading... |
245 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); | 250 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); |
246 UMA_HISTOGRAM_BOOLEAN( | 251 UMA_HISTOGRAM_BOOLEAN( |
247 "NaCl.enable-nacl-debug", | 252 "NaCl.enable-nacl-debug", |
248 cmd->HasSwitch(switches::kEnableNaClDebug)); | 253 cmd->HasSwitch(switches::kEnableNaClDebug)); |
249 NaClBrowser::GetInstance()->SetDebugPatterns( | 254 NaClBrowser::GetInstance()->SetDebugPatterns( |
250 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); | 255 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); |
251 } | 256 } |
252 | 257 |
253 void NaClProcessHost::Launch( | 258 void NaClProcessHost::Launch( |
254 ChromeRenderMessageFilter* chrome_render_message_filter, | 259 ChromeRenderMessageFilter* chrome_render_message_filter, |
255 int socket_count, | |
256 IPC::Message* reply_msg, | 260 IPC::Message* reply_msg, |
257 scoped_refptr<ExtensionInfoMap> extension_info_map) { | 261 scoped_refptr<ExtensionInfoMap> extension_info_map) { |
258 chrome_render_message_filter_ = chrome_render_message_filter; | 262 chrome_render_message_filter_ = chrome_render_message_filter; |
259 reply_msg_ = reply_msg; | 263 reply_msg_ = reply_msg; |
260 extension_info_map_ = extension_info_map; | 264 extension_info_map_ = extension_info_map; |
261 | 265 |
262 // Place an arbitrary limit on the number of sockets to limit | |
263 // exposure in case the renderer is compromised. We can increase | |
264 // this if necessary. | |
265 if (socket_count > 8) { | |
266 delete this; | |
267 return; | |
268 } | |
269 | |
270 // Start getting the IRT open asynchronously while we launch the NaCl process. | 266 // Start getting the IRT open asynchronously while we launch the NaCl process. |
271 // We'll make sure this actually finished in StartWithLaunchedProcess, below. | 267 // We'll make sure this actually finished in StartWithLaunchedProcess, below. |
272 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 268 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
273 nacl_browser->EnsureAllResourcesAvailable(); | 269 nacl_browser->EnsureAllResourcesAvailable(); |
274 if (!nacl_browser->IsOk()) { | 270 if (!nacl_browser->IsOk()) { |
275 DLOG(ERROR) << "Cannot launch NaCl process"; | 271 DLOG(ERROR) << "Cannot launch NaCl process"; |
276 delete this; | 272 delete this; |
277 return; | 273 return; |
278 } | 274 } |
279 | 275 |
280 // Rather than creating a socket pair in the renderer, and passing | 276 // Rather than creating a socket pair in the renderer, and passing |
281 // one side through the browser to sel_ldr, socket pairs are created | 277 // one side through the browser to sel_ldr, socket pairs are created |
282 // in the browser and then passed to the renderer and sel_ldr. | 278 // in the browser and then passed to the renderer and sel_ldr. |
283 // | 279 // |
284 // This is mainly for the benefit of Windows, where sockets cannot | 280 // This is mainly for the benefit of Windows, where sockets cannot |
285 // be passed in messages, but are copied via DuplicateHandle(). | 281 // be passed in messages, but are copied via DuplicateHandle(). |
286 // This means the sandboxed renderer cannot send handles to the | 282 // This means the sandboxed renderer cannot send handles to the |
287 // browser process. | 283 // browser process. |
288 | 284 |
289 for (int i = 0; i < socket_count; i++) { | 285 nacl::Handle pair[2]; |
290 nacl::Handle pair[2]; | 286 // Create a connected socket |
291 // Create a connected socket | 287 if (nacl::SocketPair(pair) == -1) { |
292 if (nacl::SocketPair(pair) == -1) { | 288 delete this; |
293 delete this; | 289 return; |
294 return; | |
295 } | |
296 internal_->sockets_for_renderer.push_back(pair[0]); | |
297 internal_->sockets_for_sel_ldr.push_back(pair[1]); | |
298 SetCloseOnExec(pair[0]); | |
299 SetCloseOnExec(pair[1]); | |
300 } | 290 } |
| 291 internal_->socket_for_renderer = pair[0]; |
| 292 internal_->socket_for_sel_ldr = pair[1]; |
| 293 SetCloseOnExec(pair[0]); |
| 294 SetCloseOnExec(pair[1]); |
301 | 295 |
302 // Launch the process | 296 // Launch the process |
303 if (!LaunchSelLdr()) { | 297 if (!LaunchSelLdr()) { |
304 delete this; | 298 delete this; |
305 } | 299 } |
306 } | 300 } |
307 | 301 |
308 #if defined(OS_WIN) | 302 #if defined(OS_WIN) |
309 void NaClProcessHost::OnChannelConnected(int32 peer_pid) { | 303 void NaClProcessHost::OnChannelConnected(int32 peer_pid) { |
310 // Set process handle, if it was not set previously. | 304 // Set process handle, if it was not set previously. |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 void NaClProcessHost::OnResourcesReady() { | 605 void NaClProcessHost::OnResourcesReady() { |
612 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 606 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
613 if (!nacl_browser->IsReady() || !SendStart()) { | 607 if (!nacl_browser->IsReady() || !SendStart()) { |
614 DLOG(ERROR) << "Cannot launch NaCl process"; | 608 DLOG(ERROR) << "Cannot launch NaCl process"; |
615 delete this; | 609 delete this; |
616 } | 610 } |
617 } | 611 } |
618 | 612 |
619 bool NaClProcessHost::ReplyToRenderer( | 613 bool NaClProcessHost::ReplyToRenderer( |
620 const IPC::ChannelHandle& channel_handle) { | 614 const IPC::ChannelHandle& channel_handle) { |
621 std::vector<nacl::FileDescriptor> handles_for_renderer; | 615 nacl::FileDescriptor handle_for_renderer; |
622 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | |
623 #if defined(OS_WIN) | 616 #if defined(OS_WIN) |
624 // Copy the handle into the renderer process. | 617 // Copy the handle into the renderer process. |
625 HANDLE handle_in_renderer; | 618 HANDLE handle_in_renderer; |
626 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 619 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
627 reinterpret_cast<HANDLE>( | 620 reinterpret_cast<HANDLE>( |
628 internal_->sockets_for_renderer[i]), | 621 internal_->socket_for_renderer), |
629 chrome_render_message_filter_->peer_handle(), | 622 chrome_render_message_filter_->peer_handle(), |
630 &handle_in_renderer, | 623 &handle_in_renderer, |
631 0, // Unused given DUPLICATE_SAME_ACCESS. | 624 0, // Unused given DUPLICATE_SAME_ACCESS. |
632 FALSE, | 625 FALSE, |
633 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 626 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
634 DLOG(ERROR) << "DuplicateHandle() failed"; | 627 DLOG(ERROR) << "DuplicateHandle() failed"; |
635 return false; | 628 return false; |
636 } | 629 } |
637 handles_for_renderer.push_back( | 630 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( |
638 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); | 631 handle_in_renderer); |
639 #else | 632 #else |
640 // No need to dup the imc_handle - we don't pass it anywhere else so | 633 // No need to dup the imc_handle - we don't pass it anywhere else so |
641 // it cannot be closed. | 634 // it cannot be closed. |
642 nacl::FileDescriptor imc_handle; | 635 nacl::FileDescriptor imc_handle; |
643 imc_handle.fd = internal_->sockets_for_renderer[i]; | 636 imc_handle.fd = internal_->socket_for_renderer; |
644 imc_handle.auto_close = true; | 637 imc_handle.auto_close = true; |
645 handles_for_renderer.push_back(imc_handle); | 638 handle_for_renderer = imc_handle; |
646 #endif | 639 #endif |
647 } | |
648 | 640 |
649 #if defined(OS_WIN) | 641 #if defined(OS_WIN) |
650 // If we are on 64-bit Windows, the NaCl process's sandbox is | 642 // If we are on 64-bit Windows, the NaCl process's sandbox is |
651 // managed by a different process from the renderer's sandbox. We | 643 // managed by a different process from the renderer's sandbox. We |
652 // need to inform the renderer's sandbox about the NaCl process so | 644 // need to inform the renderer's sandbox about the NaCl process so |
653 // that the renderer can send handles to the NaCl process using | 645 // that the renderer can send handles to the NaCl process using |
654 // BrokerDuplicateHandle(). | 646 // BrokerDuplicateHandle(). |
655 if (RunningOnWOW64()) { | 647 if (RunningOnWOW64()) { |
656 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 648 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
657 DLOG(ERROR) << "Failed to add NaCl process PID"; | 649 DLOG(ERROR) << "Failed to add NaCl process PID"; |
658 return false; | 650 return false; |
659 } | 651 } |
660 } | 652 } |
661 #endif | 653 #endif |
662 | 654 |
663 const ChildProcessData& data = process_->GetData(); | 655 const ChildProcessData& data = process_->GetData(); |
664 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( | 656 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( |
665 reply_msg_, handles_for_renderer, | 657 reply_msg_, handle_for_renderer, |
666 channel_handle, base::GetProcId(data.handle), data.id); | 658 channel_handle, base::GetProcId(data.handle), data.id); |
667 chrome_render_message_filter_->Send(reply_msg_); | 659 chrome_render_message_filter_->Send(reply_msg_); |
668 chrome_render_message_filter_ = NULL; | 660 chrome_render_message_filter_ = NULL; |
669 reply_msg_ = NULL; | 661 reply_msg_ = NULL; |
670 internal_->sockets_for_renderer.clear(); | 662 internal_->socket_for_renderer = nacl::kInvalidHandle; |
671 return true; | 663 return true; |
672 } | 664 } |
673 | 665 |
674 // TCP port we chose for NaCl debug stub. It can be any other number. | 666 // TCP port we chose for NaCl debug stub. It can be any other number. |
675 static const int kDebugStubPort = 4014; | 667 static const int kDebugStubPort = 4014; |
676 | 668 |
677 #if defined(OS_POSIX) | 669 #if defined(OS_POSIX) |
678 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { | 670 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { |
679 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 671 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
680 SocketDescriptor s; | 672 SocketDescriptor s; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 params.version = chrome::VersionInfo().CreateVersionString(); | 704 params.version = chrome::VersionInfo().CreateVersionString(); |
713 params.enable_exception_handling = enable_exception_handling_; | 705 params.enable_exception_handling = enable_exception_handling_; |
714 params.enable_debug_stub = enable_debug_stub_ && | 706 params.enable_debug_stub = enable_debug_stub_ && |
715 NaClBrowser::GetInstance()->URLMatchesDebugPatterns(manifest_url_); | 707 NaClBrowser::GetInstance()->URLMatchesDebugPatterns(manifest_url_); |
716 params.enable_ipc_proxy = enable_ipc_proxy_; | 708 params.enable_ipc_proxy = enable_ipc_proxy_; |
717 | 709 |
718 base::PlatformFile irt_file = nacl_browser->IrtFile(); | 710 base::PlatformFile irt_file = nacl_browser->IrtFile(); |
719 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); | 711 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); |
720 | 712 |
721 const ChildProcessData& data = process_->GetData(); | 713 const ChildProcessData& data = process_->GetData(); |
722 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 714 if (!ShareHandleToSelLdr(data.handle, |
723 if (!ShareHandleToSelLdr(data.handle, | 715 internal_->socket_for_sel_ldr, true, |
724 internal_->sockets_for_sel_ldr[i], true, | 716 ¶ms.handles)) { |
725 ¶ms.handles)) { | 717 return false; |
726 return false; | |
727 } | |
728 } | 718 } |
729 | 719 |
730 // Send over the IRT file handle. We don't close our own copy! | 720 // Send over the IRT file handle. We don't close our own copy! |
731 if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) | 721 if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) |
732 return false; | 722 return false; |
733 | 723 |
734 #if defined(OS_MACOSX) | 724 #if defined(OS_MACOSX) |
735 // For dynamic loading support, NaCl requires a file descriptor that | 725 // For dynamic loading support, NaCl requires a file descriptor that |
736 // was created in /tmp, since those created with shm_open() are not | 726 // was created in /tmp, since those created with shm_open() are not |
737 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 727 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
(...skipping 21 matching lines...) Expand all Loading... |
759 SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 749 SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); |
760 if (server_bound_socket != net::TCPListenSocket::kInvalidSocket) { | 750 if (server_bound_socket != net::TCPListenSocket::kInvalidSocket) { |
761 params.debug_stub_server_bound_socket = | 751 params.debug_stub_server_bound_socket = |
762 nacl::FileDescriptor(server_bound_socket, true); | 752 nacl::FileDescriptor(server_bound_socket, true); |
763 } | 753 } |
764 } | 754 } |
765 #endif | 755 #endif |
766 | 756 |
767 process_->Send(new NaClProcessMsg_Start(params)); | 757 process_->Send(new NaClProcessMsg_Start(params)); |
768 | 758 |
769 internal_->sockets_for_sel_ldr.clear(); | 759 internal_->socket_for_sel_ldr = nacl::kInvalidHandle; |
770 return true; | 760 return true; |
771 } | 761 } |
772 | 762 |
773 bool NaClProcessHost::SendStart() { | 763 bool NaClProcessHost::SendStart() { |
774 if (!enable_ipc_proxy_) { | 764 if (!enable_ipc_proxy_) { |
775 if (!ReplyToRenderer(IPC::ChannelHandle())) | 765 if (!ReplyToRenderer(IPC::ChannelHandle())) |
776 return false; | 766 return false; |
777 } | 767 } |
778 return StartNaClExecution(); | 768 return StartNaClExecution(); |
779 } | 769 } |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 } else { | 921 } else { |
932 NaClStartDebugExceptionHandlerThread( | 922 NaClStartDebugExceptionHandlerThread( |
933 process_handle.Take(), info, | 923 process_handle.Take(), info, |
934 base::MessageLoopProxy::current(), | 924 base::MessageLoopProxy::current(), |
935 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 925 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
936 weak_factory_.GetWeakPtr())); | 926 weak_factory_.GetWeakPtr())); |
937 return true; | 927 return true; |
938 } | 928 } |
939 } | 929 } |
940 #endif | 930 #endif |
OLD | NEW |