Chromium Code Reviews| 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 <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #if defined(OS_POSIX) | 10 #if defined(OS_POSIX) |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { | 256 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
| 257 bool handled = true; | 257 bool handled = true; |
| 258 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) | 258 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
| 259 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) | 259 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) |
| 260 IPC_MESSAGE_UNHANDLED(handled = false) | 260 IPC_MESSAGE_UNHANDLED(handled = false) |
| 261 IPC_END_MESSAGE_MAP() | 261 IPC_END_MESSAGE_MAP() |
| 262 return handled; | 262 return handled; |
| 263 } | 263 } |
| 264 | 264 |
| 265 void NaClListener::OnStart(const nacl::NaClStartParams& params) { | 265 void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
| 266 #if !defined(OS_LINUX) | 266 if (uses_nonsfi_mode_) { |
| 267 CHECK(!uses_nonsfi_mode_) << "Non-SFI NaCl is only supported on Linux"; | 267 StartNonSfi(params); |
| 268 #endif | 268 return; |
| 269 } | |
| 269 | 270 |
| 270 // Random number source initialization. | 271 #if defined(OS_LINUX) || defined(OS_MACOSX) |
| 271 #if defined(OS_LINUX) | 272 int urandom_fd = dup(base::GetUrandomFD()); |
| 272 if (uses_nonsfi_mode_) { | 273 if (urandom_fd < 0) { |
| 273 nacl::nonsfi::SetUrandomFd(base::GetUrandomFD()); | 274 LOG(ERROR) << "Failed to dup() the urandom FD"; |
| 275 return; | |
| 274 } | 276 } |
| 275 #endif | 277 NaClChromeMainSetUrandomFd(urandom_fd); |
| 276 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
| 277 if (!uses_nonsfi_mode_) { | |
| 278 int urandom_fd = dup(base::GetUrandomFD()); | |
| 279 if (urandom_fd < 0) { | |
| 280 LOG(ERROR) << "Failed to dup() the urandom FD"; | |
| 281 return; | |
| 282 } | |
| 283 NaClChromeMainSetUrandomFd(urandom_fd); | |
| 284 } | |
| 285 #endif | 278 #endif |
| 286 | 279 |
| 287 struct NaClApp* nap = NULL; | 280 struct NaClApp* nap = NULL; |
| 288 if (!uses_nonsfi_mode_) { | 281 NaClChromeMainInit(); |
| 289 NaClChromeMainInit(); | 282 nap = NaClAppCreate(); |
| 290 nap = NaClAppCreate(); | 283 if (nap == NULL) { |
| 291 if (nap == NULL) { | 284 LOG(ERROR) << "NaClAppCreate() failed"; |
| 292 LOG(ERROR) << "NaClAppCreate() failed"; | 285 return; |
| 293 return; | |
| 294 } | |
| 295 } | 286 } |
| 296 | 287 |
| 297 IPC::ChannelHandle browser_handle; | 288 IPC::ChannelHandle browser_handle; |
| 298 IPC::ChannelHandle ppapi_renderer_handle; | 289 IPC::ChannelHandle ppapi_renderer_handle; |
| 299 IPC::ChannelHandle manifest_service_handle; | |
| 300 | 290 |
| 301 if (params.enable_ipc_proxy) { | 291 if (params.enable_ipc_proxy) { |
| 302 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | 292 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
| 303 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | 293 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
| 304 | 294 |
| 305 #if defined(OS_LINUX) | 295 // Create the PPAPI IPC channels between the NaCl IRT and the host |
| 306 if (uses_nonsfi_mode_) { | 296 // (browser/renderer) processes. The IRT uses these channels to |
| 307 manifest_service_handle = | 297 // communicate with the host and to initialize the IPC dispatchers. |
| 308 IPC::Channel::GenerateVerifiedChannelID("nacl"); | 298 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), |
| 309 | 299 nap, NACL_CHROME_DESC_BASE); |
| 310 // In non-SFI mode, we neither intercept nor rewrite the message using | 300 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), |
| 311 // NaClIPCAdapter, and the channels are connected between the plugin and | 301 nap, NACL_CHROME_DESC_BASE + 1); |
| 312 // the hosts directly. So, the IPC::Channel instances will be created in | |
| 313 // the plugin side, because the IPC::Listener needs to live on the | |
| 314 // plugin's main thread. However, on initialization (i.e. before loading | |
| 315 // the plugin binary), the FD needs to be passed to the hosts. So, here | |
| 316 // we create raw FD pairs, and pass the client side FDs to the hosts, | |
| 317 // and the server side FDs to the plugin. | |
| 318 int browser_server_ppapi_fd; | |
| 319 int browser_client_ppapi_fd; | |
| 320 int renderer_server_ppapi_fd; | |
| 321 int renderer_client_ppapi_fd; | |
| 322 int manifest_service_server_fd; | |
| 323 int manifest_service_client_fd; | |
| 324 if (!IPC::SocketPair( | |
| 325 &browser_server_ppapi_fd, &browser_client_ppapi_fd) || | |
| 326 !IPC::SocketPair( | |
| 327 &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || | |
| 328 !IPC::SocketPair( | |
| 329 &manifest_service_server_fd, &manifest_service_client_fd)) { | |
| 330 LOG(ERROR) << "Failed to create sockets for IPC."; | |
| 331 return; | |
| 332 } | |
| 333 | |
| 334 // Set the plugin IPC channel FDs. | |
| 335 ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, | |
| 336 renderer_server_ppapi_fd, | |
| 337 manifest_service_server_fd); | |
| 338 ppapi::StartUpPlugin(); | |
| 339 | |
| 340 // Send back to the client side IPC channel FD to the host. | |
| 341 browser_handle.socket = | |
| 342 base::FileDescriptor(browser_client_ppapi_fd, true); | |
| 343 ppapi_renderer_handle.socket = | |
| 344 base::FileDescriptor(renderer_client_ppapi_fd, true); | |
| 345 manifest_service_handle.socket = | |
| 346 base::FileDescriptor(manifest_service_client_fd, true); | |
| 347 } else { | |
| 348 #endif | |
| 349 // Create the PPAPI IPC channels between the NaCl IRT and the host | |
| 350 // (browser/renderer) processes. The IRT uses these channels to | |
| 351 // communicate with the host and to initialize the IPC dispatchers. | |
| 352 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), | |
| 353 nap, NACL_CHROME_DESC_BASE); | |
| 354 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), | |
| 355 nap, NACL_CHROME_DESC_BASE + 1); | |
| 356 #if defined(OS_LINUX) | |
| 357 } | |
| 358 #endif | |
| 359 } | 302 } |
| 360 | 303 |
| 361 // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". | 304 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( |
| 362 // Using an alternate channel name prevents the pipe from being created on | 305 io_thread_.message_loop_proxy(), &shutdown_event_); |
| 363 // Windows when the sandbox is enabled. | 306 |
| 364 IPC::ChannelHandle trusted_renderer_handle = | |
| 365 IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 366 trusted_listener_ = new NaClTrustedListener( | |
| 367 trusted_renderer_handle, io_thread_.message_loop_proxy(), | |
| 368 &shutdown_event_); | |
| 369 #if defined(OS_POSIX) | |
| 370 trusted_renderer_handle.socket = base::FileDescriptor( | |
| 371 trusted_listener_->TakeClientFileDescriptor(), true); | |
| 372 #endif | |
| 373 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | 307 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
| 374 browser_handle, ppapi_renderer_handle, | 308 browser_handle, ppapi_renderer_handle, |
| 375 trusted_renderer_handle, manifest_service_handle))) | 309 trusted_renderer_handle, IPC::ChannelHandle()))) |
| 376 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | 310 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; |
| 377 | 311 |
| 378 std::vector<nacl::FileDescriptor> handles = params.handles; | 312 std::vector<nacl::FileDescriptor> handles = params.handles; |
| 379 | |
| 380 #if defined(OS_LINUX) | |
| 381 if (uses_nonsfi_mode_) { | |
| 382 // Ensure that the validation cache key (used as an extra input to the | |
| 383 // validation cache's hashing) isn't exposed accidentally. | |
| 384 CHECK(!params.validation_cache_enabled); | |
| 385 CHECK(params.validation_cache_key.size() == 0); | |
| 386 CHECK(params.version.size() == 0); | |
| 387 // Ensure that a debug stub FD isn't passed through accidentally. | |
| 388 CHECK(!params.enable_debug_stub); | |
| 389 CHECK(params.debug_stub_server_bound_socket.fd == -1); | |
| 390 | |
| 391 CHECK(!params.uses_irt); | |
| 392 CHECK(handles.size() == 1); | |
| 393 int imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]); | |
| 394 nacl::nonsfi::MainStart(imc_bootstrap_handle); | |
| 395 return; | |
| 396 } | |
| 397 #endif | |
| 398 | |
| 399 struct NaClChromeMainArgs* args = NaClChromeMainArgsCreate(); | 313 struct NaClChromeMainArgs* args = NaClChromeMainArgsCreate(); |
| 400 if (args == NULL) { | 314 if (args == NULL) { |
| 401 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; | 315 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; |
| 402 return; | 316 return; |
| 403 } | 317 } |
| 404 | 318 |
| 405 #if defined(OS_LINUX) || defined(OS_MACOSX) | 319 #if defined(OS_LINUX) || defined(OS_MACOSX) |
| 406 args->number_of_cores = number_of_cores_; | 320 args->number_of_cores = number_of_cores_; |
| 407 args->create_memory_object_func = CreateMemoryObject; | 321 args->create_memory_object_func = CreateMemoryObject; |
| 408 # if defined(OS_MACOSX) | 322 # if defined(OS_MACOSX) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 args->debug_stub_server_port_selected_handler_func = | 385 args->debug_stub_server_port_selected_handler_func = |
| 472 DebugStubPortSelectedHandler; | 386 DebugStubPortSelectedHandler; |
| 473 #endif | 387 #endif |
| 474 #if defined(OS_LINUX) | 388 #if defined(OS_LINUX) |
| 475 args->prereserved_sandbox_size = prereserved_sandbox_size_; | 389 args->prereserved_sandbox_size = prereserved_sandbox_size_; |
| 476 #endif | 390 #endif |
| 477 | 391 |
| 478 NaClChromeMainStartApp(nap, args); | 392 NaClChromeMainStartApp(nap, args); |
| 479 NOTREACHED(); | 393 NOTREACHED(); |
| 480 } | 394 } |
| 395 | |
| 396 void NaClListener::StartNonSfi(const nacl::NaClStartParams& params) { | |
| 397 #if !defined(OS_LINUX) | |
| 398 NOTREACHED() << "Non-SFI NaCl is only supported on Linux"; | |
| 399 #else | |
| 400 // Random number source initialization. | |
| 401 nacl::nonsfi::SetUrandomFd(base::GetUrandomFD()); | |
| 402 | |
| 403 IPC::ChannelHandle browser_handle; | |
| 404 IPC::ChannelHandle ppapi_renderer_handle; | |
| 405 IPC::ChannelHandle manifest_service_handle; | |
| 406 | |
| 407 if (params.enable_ipc_proxy) { | |
| 408 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
|
Mark Seaborn
2014/05/30 15:36:29
Optional: I think that using GenerateVerifiedChann
| |
| 409 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 410 manifest_service_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 411 | |
| 412 // In non-SFI mode, we neither intercept nor rewrite the message using | |
| 413 // NaClIPCAdapter, and the channels are connected between the plugin and | |
| 414 // the hosts directly. So, the IPC::Channel instances will be created in | |
| 415 // the plugin side, because the IPC::Listener needs to live on the | |
| 416 // plugin's main thread. However, on initialization (i.e. before loading | |
| 417 // the plugin binary), the FD needs to be passed to the hosts. So, here | |
| 418 // we create raw FD pairs, and pass the client side FDs to the hosts, | |
| 419 // and the server side FDs to the plugin. | |
| 420 int browser_server_ppapi_fd; | |
| 421 int browser_client_ppapi_fd; | |
| 422 int renderer_server_ppapi_fd; | |
| 423 int renderer_client_ppapi_fd; | |
| 424 int manifest_service_server_fd; | |
| 425 int manifest_service_client_fd; | |
| 426 if (!IPC::SocketPair( | |
| 427 &browser_server_ppapi_fd, &browser_client_ppapi_fd) || | |
| 428 !IPC::SocketPair( | |
| 429 &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || | |
| 430 !IPC::SocketPair( | |
| 431 &manifest_service_server_fd, &manifest_service_client_fd)) { | |
| 432 LOG(ERROR) << "Failed to create sockets for IPC."; | |
| 433 return; | |
| 434 } | |
| 435 | |
| 436 // Set the plugin IPC channel FDs. | |
| 437 ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, | |
| 438 renderer_server_ppapi_fd, | |
| 439 manifest_service_server_fd); | |
| 440 ppapi::StartUpPlugin(); | |
| 441 | |
| 442 // Send back to the client side IPC channel FD to the host. | |
| 443 browser_handle.socket = | |
| 444 base::FileDescriptor(browser_client_ppapi_fd, true); | |
| 445 ppapi_renderer_handle.socket = | |
| 446 base::FileDescriptor(renderer_client_ppapi_fd, true); | |
| 447 manifest_service_handle.socket = | |
| 448 base::FileDescriptor(manifest_service_client_fd, true); | |
| 449 } | |
| 450 | |
| 451 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( | |
|
Mark Seaborn
2014/05/30 15:36:29
I'm not sure what you have planned for NaClTrusted
| |
| 452 io_thread_.message_loop_proxy(), &shutdown_event_); | |
| 453 | |
| 454 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | |
| 455 browser_handle, ppapi_renderer_handle, | |
| 456 trusted_renderer_handle, manifest_service_handle))) | |
| 457 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | |
| 458 | |
| 459 // Ensure that the validation cache key (used as an extra input to the | |
| 460 // validation cache's hashing) isn't exposed accidentally. | |
| 461 CHECK(!params.validation_cache_enabled); | |
| 462 CHECK(params.validation_cache_key.size() == 0); | |
| 463 CHECK(params.version.size() == 0); | |
| 464 // Ensure that a debug stub FD isn't passed through accidentally. | |
| 465 CHECK(!params.enable_debug_stub); | |
| 466 CHECK(params.debug_stub_server_bound_socket.fd == -1); | |
| 467 | |
| 468 CHECK(!params.uses_irt); | |
| 469 CHECK(params.handles.size() == 1); | |
| 470 int imc_bootstrap_handle = nacl::ToNativeHandle(params.handles[0]); | |
| 471 nacl::nonsfi::MainStart(imc_bootstrap_handle); | |
| 472 return; | |
|
Mark Seaborn
2014/05/30 15:36:29
return statement is not needed.
| |
| 473 #endif // defined(OS_LINUX) | |
| 474 } | |
| 475 | |
| 476 IPC::ChannelHandle NaClListener::CreateTrustedListener( | |
| 477 base::MessageLoopProxy* message_loop_proxy, | |
| 478 base::WaitableEvent* shutdown_event) { | |
| 479 // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". | |
| 480 // Using an alternate channel name prevents the pipe from being created on | |
| 481 // Windows when the sandbox is enabled. | |
| 482 IPC::ChannelHandle trusted_renderer_handle = | |
| 483 IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 484 trusted_listener_ = new NaClTrustedListener( | |
| 485 trusted_renderer_handle, io_thread_.message_loop_proxy(), | |
| 486 &shutdown_event_); | |
| 487 #if defined(OS_POSIX) | |
| 488 trusted_renderer_handle.socket = base::FileDescriptor( | |
| 489 trusted_listener_->TakeClientFileDescriptor(), true); | |
| 490 #endif | |
| 491 return trusted_renderer_handle; | |
| 492 } | |
| OLD | NEW |