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 std::vector<nacl::Handle> sockets_for_sel_ldr; |
Mark Seaborn
2013/01/08 00:40:57
You can simplify sockets_for_sel_ldr too. It's on
jvoung (off chromium)
2013/01/08 19:35:39
Done.
| |
132 | |
133 NaClInternal() : socket_for_renderer(nacl::kInvalidHandle) { } | |
132 }; | 134 }; |
133 | 135 |
134 // ----------------------------------------------------------------------------- | 136 // ----------------------------------------------------------------------------- |
135 | 137 |
136 NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host) | 138 NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host) |
137 : host_(host) { | 139 : host_(host) { |
138 } | 140 } |
139 | 141 |
140 bool NaClProcessHost::PluginListener::OnMessageReceived( | 142 bool NaClProcessHost::PluginListener::OnMessageReceived( |
141 const IPC::Message& msg) { | 143 const IPC::Message& msg) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 process_->GetTerminationStatus(&exit_code); | 199 process_->GetTerminationStatus(&exit_code); |
198 std::string message = | 200 std::string message = |
199 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 201 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
200 exit_code, exit_code); | 202 exit_code, exit_code); |
201 if (exit_code == 0) { | 203 if (exit_code == 0) { |
202 LOG(INFO) << message; | 204 LOG(INFO) << message; |
203 } else { | 205 } else { |
204 LOG(ERROR) << message; | 206 LOG(ERROR) << message; |
205 } | 207 } |
206 | 208 |
207 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | 209 if (internal_->socket_for_renderer != nacl::kInvalidHandle) { |
208 if (nacl::Close(internal_->sockets_for_renderer[i]) != 0) { | 210 if (nacl::Close(internal_->socket_for_renderer) != 0) { |
209 NOTREACHED() << "nacl::Close() failed"; | 211 NOTREACHED() << "nacl::Close() failed"; |
210 } | 212 } |
211 } | 213 } |
214 | |
212 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 215 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
213 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { | 216 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { |
214 NOTREACHED() << "nacl::Close() failed"; | 217 NOTREACHED() << "nacl::Close() failed"; |
215 } | 218 } |
216 } | 219 } |
217 | 220 |
218 if (reply_msg_) { | 221 if (reply_msg_) { |
219 // The process failed to launch for some reason. | 222 // The process failed to launch for some reason. |
220 // Don't keep the renderer hanging. | 223 // Don't keep the renderer hanging. |
221 reply_msg_->set_reply_error(); | 224 reply_msg_->set_reply_error(); |
(...skipping 23 matching lines...) Expand all Loading... | |
245 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); | 248 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); |
246 UMA_HISTOGRAM_BOOLEAN( | 249 UMA_HISTOGRAM_BOOLEAN( |
247 "NaCl.enable-nacl-debug", | 250 "NaCl.enable-nacl-debug", |
248 cmd->HasSwitch(switches::kEnableNaClDebug)); | 251 cmd->HasSwitch(switches::kEnableNaClDebug)); |
249 NaClBrowser::GetInstance()->SetDebugPatterns( | 252 NaClBrowser::GetInstance()->SetDebugPatterns( |
250 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); | 253 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); |
251 } | 254 } |
252 | 255 |
253 void NaClProcessHost::Launch( | 256 void NaClProcessHost::Launch( |
254 ChromeRenderMessageFilter* chrome_render_message_filter, | 257 ChromeRenderMessageFilter* chrome_render_message_filter, |
255 int socket_count, | |
256 IPC::Message* reply_msg, | 258 IPC::Message* reply_msg, |
257 scoped_refptr<ExtensionInfoMap> extension_info_map) { | 259 scoped_refptr<ExtensionInfoMap> extension_info_map) { |
258 chrome_render_message_filter_ = chrome_render_message_filter; | 260 chrome_render_message_filter_ = chrome_render_message_filter; |
259 reply_msg_ = reply_msg; | 261 reply_msg_ = reply_msg; |
260 extension_info_map_ = extension_info_map; | 262 extension_info_map_ = extension_info_map; |
261 | 263 |
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. | 264 // Start getting the IRT open asynchronously while we launch the NaCl process. |
271 // We'll make sure this actually finished in StartWithLaunchedProcess, below. | 265 // We'll make sure this actually finished in StartWithLaunchedProcess, below. |
272 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 266 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
273 nacl_browser->EnsureAllResourcesAvailable(); | 267 nacl_browser->EnsureAllResourcesAvailable(); |
274 if (!nacl_browser->IsOk()) { | 268 if (!nacl_browser->IsOk()) { |
275 DLOG(ERROR) << "Cannot launch NaCl process"; | 269 DLOG(ERROR) << "Cannot launch NaCl process"; |
276 delete this; | 270 delete this; |
277 return; | 271 return; |
278 } | 272 } |
279 | 273 |
280 // Rather than creating a socket pair in the renderer, and passing | 274 // Rather than creating a socket pair in the renderer, and passing |
281 // one side through the browser to sel_ldr, socket pairs are created | 275 // 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. | 276 // in the browser and then passed to the renderer and sel_ldr. |
283 // | 277 // |
284 // This is mainly for the benefit of Windows, where sockets cannot | 278 // This is mainly for the benefit of Windows, where sockets cannot |
285 // be passed in messages, but are copied via DuplicateHandle(). | 279 // be passed in messages, but are copied via DuplicateHandle(). |
286 // This means the sandboxed renderer cannot send handles to the | 280 // This means the sandboxed renderer cannot send handles to the |
287 // browser process. | 281 // browser process. |
288 | 282 |
289 for (int i = 0; i < socket_count; i++) { | 283 nacl::Handle pair[2]; |
290 nacl::Handle pair[2]; | 284 // Create a connected socket |
291 // Create a connected socket | 285 if (nacl::SocketPair(pair) == -1) { |
292 if (nacl::SocketPair(pair) == -1) { | 286 delete this; |
293 delete this; | 287 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 } | 288 } |
289 internal_->socket_for_renderer = pair[0]; | |
290 internal_->sockets_for_sel_ldr.push_back(pair[1]); | |
291 SetCloseOnExec(pair[0]); | |
292 SetCloseOnExec(pair[1]); | |
301 | 293 |
302 // Launch the process | 294 // Launch the process |
303 if (!LaunchSelLdr()) { | 295 if (!LaunchSelLdr()) { |
304 delete this; | 296 delete this; |
305 } | 297 } |
306 } | 298 } |
307 | 299 |
308 #if defined(OS_WIN) | 300 #if defined(OS_WIN) |
309 void NaClProcessHost::OnChannelConnected(int32 peer_pid) { | 301 void NaClProcessHost::OnChannelConnected(int32 peer_pid) { |
310 // Set process handle, if it was not set previously. | 302 // 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() { | 603 void NaClProcessHost::OnResourcesReady() { |
612 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 604 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
613 if (!nacl_browser->IsReady() || !SendStart()) { | 605 if (!nacl_browser->IsReady() || !SendStart()) { |
614 DLOG(ERROR) << "Cannot launch NaCl process"; | 606 DLOG(ERROR) << "Cannot launch NaCl process"; |
615 delete this; | 607 delete this; |
616 } | 608 } |
617 } | 609 } |
618 | 610 |
619 bool NaClProcessHost::ReplyToRenderer( | 611 bool NaClProcessHost::ReplyToRenderer( |
620 const IPC::ChannelHandle& channel_handle) { | 612 const IPC::ChannelHandle& channel_handle) { |
621 std::vector<nacl::FileDescriptor> handles_for_renderer; | 613 nacl::FileDescriptor handle_for_renderer; |
622 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | |
623 #if defined(OS_WIN) | 614 #if defined(OS_WIN) |
624 // Copy the handle into the renderer process. | 615 // Copy the handle into the renderer process. |
625 HANDLE handle_in_renderer; | 616 HANDLE handle_in_renderer; |
626 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 617 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
627 reinterpret_cast<HANDLE>( | 618 reinterpret_cast<HANDLE>( |
628 internal_->sockets_for_renderer[i]), | 619 internal_->socket_for_renderer), |
629 chrome_render_message_filter_->peer_handle(), | 620 chrome_render_message_filter_->peer_handle(), |
630 &handle_in_renderer, | 621 &handle_in_renderer, |
631 0, // Unused given DUPLICATE_SAME_ACCESS. | 622 0, // Unused given DUPLICATE_SAME_ACCESS. |
632 FALSE, | 623 FALSE, |
633 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 624 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
634 DLOG(ERROR) << "DuplicateHandle() failed"; | 625 DLOG(ERROR) << "DuplicateHandle() failed"; |
635 return false; | 626 return false; |
636 } | 627 } |
637 handles_for_renderer.push_back( | 628 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( |
638 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); | 629 handle_in_renderer); |
639 #else | 630 #else |
640 // No need to dup the imc_handle - we don't pass it anywhere else so | 631 // No need to dup the imc_handle - we don't pass it anywhere else so |
641 // it cannot be closed. | 632 // it cannot be closed. |
642 nacl::FileDescriptor imc_handle; | 633 nacl::FileDescriptor imc_handle; |
643 imc_handle.fd = internal_->sockets_for_renderer[i]; | 634 imc_handle.fd = internal_->socket_for_renderer; |
644 imc_handle.auto_close = true; | 635 imc_handle.auto_close = true; |
645 handles_for_renderer.push_back(imc_handle); | 636 handle_for_renderer = imc_handle; |
646 #endif | 637 #endif |
647 } | |
648 | 638 |
649 #if defined(OS_WIN) | 639 #if defined(OS_WIN) |
650 // If we are on 64-bit Windows, the NaCl process's sandbox is | 640 // 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 | 641 // managed by a different process from the renderer's sandbox. We |
652 // need to inform the renderer's sandbox about the NaCl process so | 642 // need to inform the renderer's sandbox about the NaCl process so |
653 // that the renderer can send handles to the NaCl process using | 643 // that the renderer can send handles to the NaCl process using |
654 // BrokerDuplicateHandle(). | 644 // BrokerDuplicateHandle(). |
655 if (RunningOnWOW64()) { | 645 if (RunningOnWOW64()) { |
656 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 646 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
657 DLOG(ERROR) << "Failed to add NaCl process PID"; | 647 DLOG(ERROR) << "Failed to add NaCl process PID"; |
658 return false; | 648 return false; |
659 } | 649 } |
660 } | 650 } |
661 #endif | 651 #endif |
662 | 652 |
663 const ChildProcessData& data = process_->GetData(); | 653 const ChildProcessData& data = process_->GetData(); |
664 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( | 654 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( |
665 reply_msg_, handles_for_renderer, | 655 reply_msg_, handle_for_renderer, |
666 channel_handle, base::GetProcId(data.handle), data.id); | 656 channel_handle, base::GetProcId(data.handle), data.id); |
667 chrome_render_message_filter_->Send(reply_msg_); | 657 chrome_render_message_filter_->Send(reply_msg_); |
668 chrome_render_message_filter_ = NULL; | 658 chrome_render_message_filter_ = NULL; |
669 reply_msg_ = NULL; | 659 reply_msg_ = NULL; |
670 internal_->sockets_for_renderer.clear(); | 660 internal_->socket_for_renderer = nacl::kInvalidHandle; |
671 return true; | 661 return true; |
672 } | 662 } |
673 | 663 |
674 // TCP port we chose for NaCl debug stub. It can be any other number. | 664 // TCP port we chose for NaCl debug stub. It can be any other number. |
675 static const int kDebugStubPort = 4014; | 665 static const int kDebugStubPort = 4014; |
676 | 666 |
677 #if defined(OS_POSIX) | 667 #if defined(OS_POSIX) |
678 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { | 668 SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { |
679 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 669 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
680 SocketDescriptor s; | 670 SocketDescriptor s; |
(...skipping 250 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 |