| 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 |