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 |