OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/loader/nacl_listener.h" | 5 #include "components/nacl/loader/nacl_listener.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "native_client/src/public/chrome_main.h" | 28 #include "native_client/src/public/chrome_main.h" |
29 #include "native_client/src/public/nacl_app.h" | 29 #include "native_client/src/public/nacl_app.h" |
30 #include "native_client/src/public/nacl_file_info.h" | 30 #include "native_client/src/public/nacl_file_info.h" |
31 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" | 31 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" |
32 | 32 |
33 #if defined(OS_POSIX) | 33 #if defined(OS_POSIX) |
34 #include "base/file_descriptor_posix.h" | 34 #include "base/file_descriptor_posix.h" |
35 #endif | 35 #endif |
36 | 36 |
37 #if defined(OS_LINUX) | 37 #if defined(OS_LINUX) |
38 #include "components/nacl/loader/nonsfi/irt_random.h" | |
39 #include "components/nacl/loader/nonsfi/nonsfi_main.h" | |
40 #include "content/public/common/child_process_sandbox_support_linux.h" | 38 #include "content/public/common/child_process_sandbox_support_linux.h" |
41 #include "ppapi/nacl_irt/plugin_startup.h" | |
42 #endif | 39 #endif |
43 | 40 |
44 #if defined(OS_WIN) | 41 #if defined(OS_WIN) |
45 #include <fcntl.h> | 42 #include <fcntl.h> |
46 #include <io.h> | 43 #include <io.h> |
47 | 44 |
48 #include "content/public/common/sandbox_init.h" | 45 #include "content/public/common/sandbox_init.h" |
49 #endif | 46 #endif |
50 | 47 |
51 namespace { | 48 namespace { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 } | 197 } |
201 | 198 |
202 private: | 199 private: |
203 // The listener never dies, otherwise this might be a dangling reference. | 200 // The listener never dies, otherwise this might be a dangling reference. |
204 NaClListener* listener_; | 201 NaClListener* listener_; |
205 }; | 202 }; |
206 | 203 |
207 | 204 |
208 NaClListener::NaClListener() : shutdown_event_(true, false), | 205 NaClListener::NaClListener() : shutdown_event_(true, false), |
209 io_thread_("NaCl_IOThread"), | 206 io_thread_("NaCl_IOThread"), |
210 uses_nonsfi_mode_(false), | |
211 #if defined(OS_LINUX) | 207 #if defined(OS_LINUX) |
212 prereserved_sandbox_size_(0), | 208 prereserved_sandbox_size_(0), |
213 #endif | 209 #endif |
214 #if defined(OS_POSIX) | 210 #if defined(OS_POSIX) |
215 number_of_cores_(-1), // unknown/error | 211 number_of_cores_(-1), // unknown/error |
216 #endif | 212 #endif |
217 main_loop_(NULL) { | 213 main_loop_(NULL) { |
218 io_thread_.StartWithOptions( | 214 io_thread_.StartWithOptions( |
219 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 215 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
220 #if defined(OS_WIN) | 216 #if defined(OS_WIN) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { | 254 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
259 bool handled = true; | 255 bool handled = true; |
260 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) | 256 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
261 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) | 257 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) |
262 IPC_MESSAGE_UNHANDLED(handled = false) | 258 IPC_MESSAGE_UNHANDLED(handled = false) |
263 IPC_END_MESSAGE_MAP() | 259 IPC_END_MESSAGE_MAP() |
264 return handled; | 260 return handled; |
265 } | 261 } |
266 | 262 |
267 void NaClListener::OnStart(const nacl::NaClStartParams& params) { | 263 void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
268 if (uses_nonsfi_mode_) { | |
269 StartNonSfi(params); | |
270 return; | |
271 } | |
272 | |
273 #if defined(OS_LINUX) || defined(OS_MACOSX) | 264 #if defined(OS_LINUX) || defined(OS_MACOSX) |
274 int urandom_fd = dup(base::GetUrandomFD()); | 265 int urandom_fd = dup(base::GetUrandomFD()); |
275 if (urandom_fd < 0) { | 266 if (urandom_fd < 0) { |
276 LOG(ERROR) << "Failed to dup() the urandom FD"; | 267 LOG(ERROR) << "Failed to dup() the urandom FD"; |
277 return; | 268 return; |
278 } | 269 } |
279 NaClChromeMainSetUrandomFd(urandom_fd); | 270 NaClChromeMainSetUrandomFd(urandom_fd); |
280 #endif | 271 #endif |
281 | 272 |
282 struct NaClApp* nap = NULL; | 273 struct NaClApp* nap = NULL; |
(...skipping 13 matching lines...) Expand all Loading... |
296 | 287 |
297 // Create the PPAPI IPC channels between the NaCl IRT and the host | 288 // Create the PPAPI IPC channels between the NaCl IRT and the host |
298 // (browser/renderer) processes. The IRT uses these channels to | 289 // (browser/renderer) processes. The IRT uses these channels to |
299 // communicate with the host and to initialize the IPC dispatchers. | 290 // communicate with the host and to initialize the IPC dispatchers. |
300 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), | 291 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), |
301 nap, NACL_CHROME_DESC_BASE); | 292 nap, NACL_CHROME_DESC_BASE); |
302 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), | 293 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), |
303 nap, NACL_CHROME_DESC_BASE + 1); | 294 nap, NACL_CHROME_DESC_BASE + 1); |
304 } | 295 } |
305 | 296 |
306 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( | 297 trusted_listener_ = new NaClTrustedListener( |
307 io_thread_.message_loop_proxy(), &shutdown_event_); | 298 IPC::Channel::GenerateVerifiedChannelID("nacl"), |
| 299 io_thread_.message_loop_proxy().get()); |
308 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | 300 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
309 browser_handle, ppapi_renderer_handle, | 301 browser_handle, |
310 trusted_renderer_handle, IPC::ChannelHandle()))) | 302 ppapi_renderer_handle, |
| 303 trusted_listener_->TakeClientChannelHandle(), |
| 304 IPC::ChannelHandle()))) |
311 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | 305 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; |
312 | 306 |
313 std::vector<nacl::FileDescriptor> handles = params.handles; | 307 std::vector<nacl::FileDescriptor> handles = params.handles; |
314 struct NaClChromeMainArgs* args = NaClChromeMainArgsCreate(); | 308 struct NaClChromeMainArgs* args = NaClChromeMainArgsCreate(); |
315 if (args == NULL) { | 309 if (args == NULL) { |
316 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; | 310 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; |
317 return; | 311 return; |
318 } | 312 } |
319 | 313 |
320 #if defined(OS_LINUX) || defined(OS_MACOSX) | 314 #if defined(OS_LINUX) || defined(OS_MACOSX) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 nexe_file_info.desc = nexe_file; | 395 nexe_file_info.desc = nexe_file; |
402 #else | 396 #else |
403 #error Unsupported target platform. | 397 #error Unsupported target platform. |
404 #endif | 398 #endif |
405 nexe_file_info.file_token.lo = params.nexe_token_lo; | 399 nexe_file_info.file_token.lo = params.nexe_token_lo; |
406 nexe_file_info.file_token.hi = params.nexe_token_hi; | 400 nexe_file_info.file_token.hi = params.nexe_token_hi; |
407 args->nexe_desc = NaClDescIoFromFileInfo(nexe_file_info, NACL_ABI_O_RDONLY); | 401 args->nexe_desc = NaClDescIoFromFileInfo(nexe_file_info, NACL_ABI_O_RDONLY); |
408 | 402 |
409 NaClChromeMainStartApp(nap, args); | 403 NaClChromeMainStartApp(nap, args); |
410 } | 404 } |
411 | |
412 void NaClListener::StartNonSfi(const nacl::NaClStartParams& params) { | |
413 #if !defined(OS_LINUX) | |
414 NOTREACHED() << "Non-SFI NaCl is only supported on Linux"; | |
415 #else | |
416 // Random number source initialization. | |
417 nacl::nonsfi::SetUrandomFd(base::GetUrandomFD()); | |
418 | |
419 IPC::ChannelHandle browser_handle; | |
420 IPC::ChannelHandle ppapi_renderer_handle; | |
421 IPC::ChannelHandle manifest_service_handle; | |
422 | |
423 if (params.enable_ipc_proxy) { | |
424 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
425 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
426 manifest_service_handle = | |
427 IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
428 | |
429 // In non-SFI mode, we neither intercept nor rewrite the message using | |
430 // NaClIPCAdapter, and the channels are connected between the plugin and | |
431 // the hosts directly. So, the IPC::Channel instances will be created in | |
432 // the plugin side, because the IPC::Listener needs to live on the | |
433 // plugin's main thread. However, on initialization (i.e. before loading | |
434 // the plugin binary), the FD needs to be passed to the hosts. So, here | |
435 // we create raw FD pairs, and pass the client side FDs to the hosts, | |
436 // and the server side FDs to the plugin. | |
437 int browser_server_ppapi_fd; | |
438 int browser_client_ppapi_fd; | |
439 int renderer_server_ppapi_fd; | |
440 int renderer_client_ppapi_fd; | |
441 int manifest_service_server_fd; | |
442 int manifest_service_client_fd; | |
443 if (!IPC::SocketPair( | |
444 &browser_server_ppapi_fd, &browser_client_ppapi_fd) || | |
445 !IPC::SocketPair( | |
446 &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || | |
447 !IPC::SocketPair( | |
448 &manifest_service_server_fd, &manifest_service_client_fd)) { | |
449 LOG(ERROR) << "Failed to create sockets for IPC."; | |
450 return; | |
451 } | |
452 | |
453 // Set the plugin IPC channel FDs. | |
454 ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, | |
455 renderer_server_ppapi_fd, | |
456 manifest_service_server_fd); | |
457 ppapi::StartUpPlugin(); | |
458 | |
459 // Send back to the client side IPC channel FD to the host. | |
460 browser_handle.socket = | |
461 base::FileDescriptor(browser_client_ppapi_fd, true); | |
462 ppapi_renderer_handle.socket = | |
463 base::FileDescriptor(renderer_client_ppapi_fd, true); | |
464 manifest_service_handle.socket = | |
465 base::FileDescriptor(manifest_service_client_fd, true); | |
466 } | |
467 | |
468 // TODO(teravest): Do we plan on using this renderer handle for nexe loading | |
469 // for non-SFI? Right now, passing an empty channel handle instead causes | |
470 // hangs, so we'll keep it. | |
471 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( | |
472 io_thread_.message_loop_proxy(), &shutdown_event_); | |
473 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | |
474 browser_handle, ppapi_renderer_handle, | |
475 trusted_renderer_handle, manifest_service_handle))) | |
476 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | |
477 | |
478 // Ensure that the validation cache key (used as an extra input to the | |
479 // validation cache's hashing) isn't exposed accidentally. | |
480 CHECK(!params.validation_cache_enabled); | |
481 CHECK(params.validation_cache_key.size() == 0); | |
482 CHECK(params.version.size() == 0); | |
483 // Ensure that a debug stub FD isn't passed through accidentally. | |
484 CHECK(!params.enable_debug_stub); | |
485 CHECK(params.debug_stub_server_bound_socket.fd == -1); | |
486 | |
487 CHECK(!params.uses_irt); | |
488 CHECK(params.handles.empty()); | |
489 | |
490 CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit()); | |
491 CHECK(params.nexe_token_lo == 0); | |
492 CHECK(params.nexe_token_hi == 0); | |
493 nacl::nonsfi::MainStart( | |
494 IPC::PlatformFileForTransitToPlatformFile(params.nexe_file)); | |
495 #endif // defined(OS_LINUX) | |
496 } | |
497 | |
498 IPC::ChannelHandle NaClListener::CreateTrustedListener( | |
499 base::MessageLoopProxy* message_loop_proxy, | |
500 base::WaitableEvent* shutdown_event) { | |
501 // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". | |
502 // Using an alternate channel name prevents the pipe from being created on | |
503 // Windows when the sandbox is enabled. | |
504 IPC::ChannelHandle trusted_renderer_handle = | |
505 IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
506 trusted_listener_ = new NaClTrustedListener( | |
507 trusted_renderer_handle, io_thread_.message_loop_proxy().get()); | |
508 #if defined(OS_POSIX) | |
509 trusted_renderer_handle.socket = base::FileDescriptor( | |
510 trusted_listener_->TakeClientFileDescriptor(), true); | |
511 #endif | |
512 return trusted_renderer_handle; | |
513 } | |
OLD | NEW |