125b3c049e70834cf33790a28643ab058b507b35cBen Cheng// Copyright 2014 The Chromium Authors. All rights reserved. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng// Use of this source code is governed by a BSD-style license that can be 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng// found in the LICENSE file. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/loader/nonsfi/nonsfi_listener.h" 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "base/command_line.h" 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "base/file_descriptor_posix.h" 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "base/logging.h" 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "base/message_loop/message_loop.h" 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "base/rand_util.h" 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/common/nacl_messages.h" 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/common/nacl_types.h" 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/loader/nacl_trusted_listener.h" 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/loader/nonsfi/irt_random.h" 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "components/nacl/loader/nonsfi/nonsfi_main.h" 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "ipc/ipc_channel.h" 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "ipc/ipc_channel_handle.h" 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "ipc/ipc_switches.h" 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "ipc/ipc_sync_channel.h" 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "ppapi/nacl_irt/plugin_startup.h" 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if !defined(OS_LINUX) 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# error "non-SFI mode is supported only on linux." 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2725b3c049e70834cf33790a28643ab058b507b35cBen Chengnamespace nacl { 2825b3c049e70834cf33790a28643ab058b507b35cBen Chengnamespace nonsfi { 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3025b3c049e70834cf33790a28643ab058b507b35cBen ChengNonSfiListener::NonSfiListener() : io_thread_("NaCl_IOThread"), 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng shutdown_event_(true, false) { 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng io_thread_.StartWithOptions( 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3625b3c049e70834cf33790a28643ab058b507b35cBen ChengNonSfiListener::~NonSfiListener() { 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3925b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid NonSfiListener::Listen() { 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng channel_ = IPC::SyncChannel::Create( 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng switches::kProcessChannelID), 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC::Channel::MODE_CLIENT, 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng this, // As a Listener. 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng io_thread_.message_loop_proxy().get(), 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng true, // Create pipe now. 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &shutdown_event_); 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng base::MessageLoop::current()->Run(); 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Chengbool NonSfiListener::Send(IPC::Message* msg) { 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng DCHECK(channel_.get() != NULL); 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return channel_->Send(msg); 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5625b3c049e70834cf33790a28643ab058b507b35cBen Chengbool NonSfiListener::OnMessageReceived(const IPC::Message& msg) { 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool handled = true; 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC_BEGIN_MESSAGE_MAP(NonSfiListener, msg) 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC_MESSAGE_UNHANDLED(handled = false) 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC_END_MESSAGE_MAP() 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return handled; 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid NonSfiListener::OnStart(const nacl::NaClStartParams& params) { 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng // Random number source initialization. 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SetUrandomFd(base::GetUrandomFD()); 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC::ChannelHandle browser_handle; 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC::ChannelHandle ppapi_renderer_handle; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC::ChannelHandle manifest_service_handle; 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (params.enable_ipc_proxy) { 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng manifest_service_handle = 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng IPC::Channel::GenerateVerifiedChannelID("nacl"); 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng // In non-SFI mode, we neither intercept nor rewrite the message using 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng // NaClIPCAdapter, and the channels are connected between the plugin and 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng // the hosts directly. So, the IPC::Channel instances will be created in 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng // the plugin side, because the IPC::Listener needs to live on the 83 // plugin's main thread. However, on initialization (i.e. before loading 84 // the plugin binary), the FD needs to be passed to the hosts. So, here 85 // we create raw FD pairs, and pass the client side FDs to the hosts, 86 // and the server side FDs to the plugin. 87 int browser_server_ppapi_fd; 88 int browser_client_ppapi_fd; 89 int renderer_server_ppapi_fd; 90 int renderer_client_ppapi_fd; 91 int manifest_service_server_fd; 92 int manifest_service_client_fd; 93 if (!IPC::SocketPair( 94 &browser_server_ppapi_fd, &browser_client_ppapi_fd) || 95 !IPC::SocketPair( 96 &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || 97 !IPC::SocketPair( 98 &manifest_service_server_fd, &manifest_service_client_fd)) { 99 LOG(ERROR) << "Failed to create sockets for IPC."; 100 return; 101 } 102 103 // Set the plugin IPC channel FDs. 104 ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, 105 renderer_server_ppapi_fd, 106 manifest_service_server_fd); 107 ppapi::StartUpPlugin(); 108 109 // Send back to the client side IPC channel FD to the host. 110 browser_handle.socket = 111 base::FileDescriptor(browser_client_ppapi_fd, true); 112 ppapi_renderer_handle.socket = 113 base::FileDescriptor(renderer_client_ppapi_fd, true); 114 manifest_service_handle.socket = 115 base::FileDescriptor(manifest_service_client_fd, true); 116 } 117 118 // TODO(teravest): Do we plan on using this renderer handle for nexe loading 119 // for non-SFI? Right now, passing an empty channel handle instead causes 120 // hangs, so we'll keep it. 121 trusted_listener_ = new NaClTrustedListener( 122 IPC::Channel::GenerateVerifiedChannelID("nacl"), 123 io_thread_.message_loop_proxy().get(), 124 &shutdown_event_); 125 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( 126 browser_handle, 127 ppapi_renderer_handle, 128 trusted_listener_->TakeClientChannelHandle(), 129 manifest_service_handle))) 130 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; 131 132 // Ensure that the validation cache key (used as an extra input to the 133 // validation cache's hashing) isn't exposed accidentally. 134 CHECK(!params.validation_cache_enabled); 135 CHECK(params.validation_cache_key.size() == 0); 136 CHECK(params.version.size() == 0); 137 // Ensure that a debug stub FD isn't passed through accidentally. 138 CHECK(!params.enable_debug_stub); 139 CHECK(params.debug_stub_server_bound_socket.fd == -1); 140 141 CHECK(!params.uses_irt); 142 CHECK(params.handles.empty()); 143 144 CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit()); 145 CHECK(params.nexe_token_lo == 0); 146 CHECK(params.nexe_token_hi == 0); 147 MainStart(IPC::PlatformFileForTransitToPlatformFile(params.nexe_file)); 148} 149 150} // namespace nonsfi 151} // namespace nacl 152