| Index: components/nacl/loader/sfi_listener_delegate.cc
|
| diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/sfi_listener_delegate.cc
|
| similarity index 54%
|
| copy from components/nacl/loader/nacl_listener.cc
|
| copy to components/nacl/loader/sfi_listener_delegate.cc
|
| index 433d9417d2abd291e532156de13b676ba6c57a4c..33ce605f976c6001c06128e6970077643048bf15 100644
|
| --- a/components/nacl/loader/nacl_listener.cc
|
| +++ b/components/nacl/loader/sfi_listener_delegate.cc
|
| @@ -1,54 +1,51 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "components/nacl/loader/nacl_listener.h"
|
| +#include "components/nacl/loader/sfi_listener_delegate.h"
|
|
|
| -#include <errno.h>
|
| -#include <fcntl.h>
|
| -#include <stdlib.h>
|
| -
|
| -#if defined(OS_POSIX)
|
| -#include <unistd.h>
|
| -#endif
|
| -
|
| -#include "base/command_line.h"
|
| #include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/rand_util.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| #include "components/nacl/common/nacl_messages.h"
|
| +#include "components/nacl/common/nacl_types.h"
|
| #include "components/nacl/loader/nacl_ipc_adapter.h"
|
| #include "components/nacl/loader/nacl_validation_db.h"
|
| #include "components/nacl/loader/nacl_validation_query.h"
|
| +#include "ipc/ipc_channel.h"
|
| #include "ipc/ipc_channel_handle.h"
|
| -#include "ipc/ipc_switches.h"
|
| -#include "ipc/ipc_sync_channel.h"
|
| -#include "ipc/ipc_sync_message_filter.h"
|
| +#include "ipc/ipc_sender.h"
|
| #include "native_client/src/public/chrome_main.h"
|
| #include "native_client/src/public/nacl_app.h"
|
| #include "native_client/src/public/nacl_file_info.h"
|
| #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
|
|
|
| +#if defined(OS_WIN)
|
| +#include <fcntl.h>
|
| +#include <io.h>
|
| +#include "content/public/common/sandbox_init.h"
|
| +#endif // OS_WIN
|
| +
|
| #if defined(OS_POSIX)
|
| +#include <unistd.h>
|
| #include "base/file_descriptor_posix.h"
|
| -#endif
|
| +#include "base/rand_util.h"
|
| +#endif // OS_POSIX
|
| +
|
| +#if defined(OS_MACOSX)
|
| +#include <errno.h>
|
| +#include <sys/types.h>
|
| +#include "base/atomicops.h"
|
| +#endif // OS_MACOSX
|
|
|
| #if defined(OS_LINUX)
|
| -#include "components/nacl/loader/nonsfi/irt_random.h"
|
| -#include "components/nacl/loader/nonsfi/nonsfi_main.h"
|
| #include "content/public/common/child_process_sandbox_support_linux.h"
|
| -#include "ppapi/nacl_irt/plugin_startup.h"
|
| -#endif
|
| +#endif // OS_LINUX
|
|
|
| -#if defined(OS_WIN)
|
| -#include <fcntl.h>
|
| -#include <io.h>
|
| -
|
| -#include "content/public/common/sandbox_init.h"
|
| -#endif
|
|
|
| +namespace nacl {
|
| namespace {
|
| +
|
| #if defined(OS_MACOSX)
|
|
|
| // On Mac OS X, shm_open() works in the sandbox but does not give us
|
| @@ -89,7 +86,7 @@ int CreateMemoryObject(size_t size, int executable) {
|
|
|
| #elif defined(OS_WIN)
|
|
|
| -NaClListener* g_listener;
|
| +IPC::Sender* g_sender;
|
|
|
| // We wrap the function to convert the bool return value to an int.
|
| int BrokerDuplicateHandle(NaClHandle source_handle,
|
| @@ -105,14 +102,14 @@ int BrokerDuplicateHandle(NaClHandle source_handle,
|
| int AttachDebugExceptionHandler(const void* info, size_t info_size) {
|
| std::string info_string(reinterpret_cast<const char*>(info), info_size);
|
| bool result = false;
|
| - if (!g_listener->Send(new NaClProcessMsg_AttachDebugExceptionHandler(
|
| + if (!g_sender->Send(new NaClProcessMsg_AttachDebugExceptionHandler(
|
| info_string, &result)))
|
| return false;
|
| return result;
|
| }
|
|
|
| void DebugStubPortSelectedHandler(uint16_t port) {
|
| - g_listener->Send(new NaClProcessHostMsg_DebugStubPortSelected(port));
|
| + g_sender->Send(new NaClProcessHostMsg_DebugStubPortSelected(port));
|
| }
|
|
|
| #endif
|
| @@ -139,12 +136,10 @@ void SetUpIPCAdapter(IPC::ChannelHandle* handle,
|
| NaClAppSetDesc(nap, nacl_fd, ipc_adapter->MakeNaClDesc());
|
| }
|
|
|
| -} // namespace
|
| -
|
| class BrowserValidationDBProxy : public NaClValidationDB {
|
| public:
|
| - explicit BrowserValidationDBProxy(NaClListener* listener)
|
| - : listener_(listener) {
|
| + explicit BrowserValidationDBProxy(IPC::Sender* sender)
|
| + : sender_(sender) {
|
| }
|
|
|
| virtual bool QueryKnownToValidate(const std::string& signature) OVERRIDE {
|
| @@ -152,8 +147,8 @@ class BrowserValidationDBProxy : public NaClValidationDB {
|
| // value we're safe. For example if the message is (for some reason)
|
| // dispatched as an async message the return parameter will not be written.
|
| bool result = false;
|
| - if (!listener_->Send(new NaClProcessMsg_QueryKnownToValidate(signature,
|
| - &result))) {
|
| + if (!sender_->Send(new NaClProcessMsg_QueryKnownToValidate(signature,
|
| + &result))) {
|
| LOG(ERROR) << "Failed to query NaCl validation cache.";
|
| result = false;
|
| }
|
| @@ -162,7 +157,7 @@ class BrowserValidationDBProxy : public NaClValidationDB {
|
|
|
| virtual void SetKnownToValidate(const std::string& signature) OVERRIDE {
|
| // Caching is optional: NaCl will still work correctly if the IPC fails.
|
| - if (!listener_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) {
|
| + if (!sender_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) {
|
| LOG(ERROR) << "Failed to update NaCl validation cache.";
|
| }
|
| }
|
| @@ -176,10 +171,10 @@ class BrowserValidationDBProxy : public NaClValidationDB {
|
| }
|
| IPC::PlatformFileForTransit ipc_fd = IPC::InvalidPlatformFileForTransit();
|
| base::FilePath ipc_path;
|
| - if (!listener_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo,
|
| - file_token->hi,
|
| - &ipc_fd,
|
| - &ipc_path))) {
|
| + if (!sender_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo,
|
| + file_token->hi,
|
| + &ipc_fd,
|
| + &ipc_path))) {
|
| return false;
|
| }
|
| if (ipc_fd == IPC::InvalidPlatformFileForTransit()) {
|
| @@ -200,75 +195,41 @@ class BrowserValidationDBProxy : public NaClValidationDB {
|
| }
|
|
|
| private:
|
| - // The listener never dies, otherwise this might be a dangling reference.
|
| - NaClListener* listener_;
|
| + // Do not own the sender. Practically, this is pointing to NaClListener
|
| + // instance, which will be alive while the plugin is running.
|
| + IPC::Sender* sender_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(BrowserValidationDBProxy);
|
| };
|
|
|
| +} // namespace
|
| +
|
|
|
| -NaClListener::NaClListener() : shutdown_event_(true, false),
|
| - io_thread_("NaCl_IOThread"),
|
| - uses_nonsfi_mode_(false),
|
| +SfiListenerDelegate::SfiListenerDelegate()
|
| +#if defined(OS_POSIX)
|
| + :
|
| +#endif // OS_POSIX
|
| #if defined(OS_LINUX)
|
| - prereserved_sandbox_size_(0),
|
| -#endif
|
| + prereserved_sandbox_size_(0),
|
| +#endif // OS_LINUX
|
| #if defined(OS_POSIX)
|
| - number_of_cores_(-1), // unknown/error
|
| -#endif
|
| - main_loop_(NULL) {
|
| - io_thread_.StartWithOptions(
|
| - base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
|
| -#if defined(OS_WIN)
|
| - DCHECK(g_listener == NULL);
|
| - g_listener = this;
|
| -#endif
|
| + number_of_cores_(-1)
|
| +#endif // OS_POSIX
|
| +{
|
| }
|
|
|
| -NaClListener::~NaClListener() {
|
| - NOTREACHED();
|
| - shutdown_event_.Signal();
|
| -#if defined(OS_WIN)
|
| - g_listener = NULL;
|
| -#endif
|
| +SfiListenerDelegate::~SfiListenerDelegate() {
|
| }
|
|
|
| -bool NaClListener::Send(IPC::Message* msg) {
|
| - DCHECK(main_loop_ != NULL);
|
| - if (base::MessageLoop::current() == main_loop_) {
|
| - // This thread owns the channel.
|
| - return channel_->Send(msg);
|
| - } else {
|
| - // This thread does not own the channel.
|
| - return filter_->Send(msg);
|
| - }
|
| -}
|
| -
|
| -void NaClListener::Listen() {
|
| - std::string channel_name =
|
| - CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
|
| - switches::kProcessChannelID);
|
| - channel_ = IPC::SyncChannel::Create(
|
| - this, io_thread_.message_loop_proxy().get(), &shutdown_event_);
|
| - filter_ = new IPC::SyncMessageFilter(&shutdown_event_);
|
| - channel_->AddFilter(filter_.get());
|
| - channel_->Init(channel_name, IPC::Channel::MODE_CLIENT, true);
|
| - main_loop_ = base::MessageLoop::current();
|
| - main_loop_->Run();
|
| -}
|
| -
|
| -bool NaClListener::OnMessageReceived(const IPC::Message& msg) {
|
| - bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP(NaClListener, msg)
|
| - IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - return handled;
|
| -}
|
| -
|
| -void NaClListener::OnStart(const nacl::NaClStartParams& params) {
|
| - if (uses_nonsfi_mode_) {
|
| - StartNonSfi(params);
|
| - return;
|
| - }
|
| +void SfiListenerDelegate::Start(
|
| + const nacl::NaClStartParams& params,
|
| + scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
|
| + IPC::ChannelHandle trusted_channel_handle,
|
| + IPC::Sender* sender) {
|
| +#if defined(OS_WIN)
|
| + DCHECK(g_sender == NULL);
|
| + g_sender = sender;
|
| +#endif
|
|
|
| #if defined(OS_LINUX) || defined(OS_MACOSX)
|
| int urandom_fd = dup(base::GetUrandomFD());
|
| @@ -287,27 +248,25 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
|
| return;
|
| }
|
|
|
| - IPC::ChannelHandle browser_handle;
|
| + IPC::ChannelHandle ppapi_browser_handle;
|
| IPC::ChannelHandle ppapi_renderer_handle;
|
|
|
| if (params.enable_ipc_proxy) {
|
| - browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| + ppapi_browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
|
|
| // Create the PPAPI IPC channels between the NaCl IRT and the host
|
| // (browser/renderer) processes. The IRT uses these channels to
|
| // communicate with the host and to initialize the IPC dispatchers.
|
| - SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(),
|
| + SetUpIPCAdapter(&ppapi_browser_handle, io_message_loop_proxy,
|
| nap, NACL_CHROME_DESC_BASE);
|
| - SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(),
|
| + SetUpIPCAdapter(&ppapi_renderer_handle, io_message_loop_proxy,
|
| nap, NACL_CHROME_DESC_BASE + 1);
|
| }
|
|
|
| - IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener(
|
| - io_thread_.message_loop_proxy(), &shutdown_event_);
|
| - if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
|
| - browser_handle, ppapi_renderer_handle,
|
| - trusted_renderer_handle, IPC::ChannelHandle())))
|
| + if (!sender->Send(new NaClProcessHostMsg_PpapiChannelsCreated(
|
| + ppapi_browser_handle, ppapi_renderer_handle,
|
| + trusted_channel_handle, IPC::ChannelHandle())))
|
| LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
|
|
|
| std::vector<nacl::FileDescriptor> handles = params.handles;
|
| @@ -352,7 +311,7 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
|
| CHECK_EQ(params.validation_cache_key.length(), (size_t) 64);
|
| // The cache structure is not freed and exists until the NaCl process exits.
|
| args->validation_cache = CreateValidationCache(
|
| - new BrowserValidationDBProxy(this), params.validation_cache_key,
|
| + new BrowserValidationDBProxy(sender), params.validation_cache_key,
|
| params.version);
|
| }
|
|
|
| @@ -409,105 +368,4 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
|
| NaClChromeMainStartApp(nap, args);
|
| }
|
|
|
| -void NaClListener::StartNonSfi(const nacl::NaClStartParams& params) {
|
| -#if !defined(OS_LINUX)
|
| - NOTREACHED() << "Non-SFI NaCl is only supported on Linux";
|
| -#else
|
| - // Random number source initialization.
|
| - nacl::nonsfi::SetUrandomFd(base::GetUrandomFD());
|
| -
|
| - IPC::ChannelHandle browser_handle;
|
| - IPC::ChannelHandle ppapi_renderer_handle;
|
| - IPC::ChannelHandle manifest_service_handle;
|
| -
|
| - if (params.enable_ipc_proxy) {
|
| - browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| - ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| - manifest_service_handle =
|
| - IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| -
|
| - // In non-SFI mode, we neither intercept nor rewrite the message using
|
| - // NaClIPCAdapter, and the channels are connected between the plugin and
|
| - // the hosts directly. So, the IPC::Channel instances will be created in
|
| - // the plugin side, because the IPC::Listener needs to live on the
|
| - // plugin's main thread. However, on initialization (i.e. before loading
|
| - // the plugin binary), the FD needs to be passed to the hosts. So, here
|
| - // we create raw FD pairs, and pass the client side FDs to the hosts,
|
| - // and the server side FDs to the plugin.
|
| - int browser_server_ppapi_fd;
|
| - int browser_client_ppapi_fd;
|
| - int renderer_server_ppapi_fd;
|
| - int renderer_client_ppapi_fd;
|
| - int manifest_service_server_fd;
|
| - int manifest_service_client_fd;
|
| - if (!IPC::SocketPair(
|
| - &browser_server_ppapi_fd, &browser_client_ppapi_fd) ||
|
| - !IPC::SocketPair(
|
| - &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) ||
|
| - !IPC::SocketPair(
|
| - &manifest_service_server_fd, &manifest_service_client_fd)) {
|
| - LOG(ERROR) << "Failed to create sockets for IPC.";
|
| - return;
|
| - }
|
| -
|
| - // Set the plugin IPC channel FDs.
|
| - ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd,
|
| - renderer_server_ppapi_fd,
|
| - manifest_service_server_fd);
|
| - ppapi::StartUpPlugin();
|
| -
|
| - // Send back to the client side IPC channel FD to the host.
|
| - browser_handle.socket =
|
| - base::FileDescriptor(browser_client_ppapi_fd, true);
|
| - ppapi_renderer_handle.socket =
|
| - base::FileDescriptor(renderer_client_ppapi_fd, true);
|
| - manifest_service_handle.socket =
|
| - base::FileDescriptor(manifest_service_client_fd, true);
|
| - }
|
| -
|
| - // TODO(teravest): Do we plan on using this renderer handle for nexe loading
|
| - // for non-SFI? Right now, passing an empty channel handle instead causes
|
| - // hangs, so we'll keep it.
|
| - IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener(
|
| - io_thread_.message_loop_proxy(), &shutdown_event_);
|
| - if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
|
| - browser_handle, ppapi_renderer_handle,
|
| - trusted_renderer_handle, manifest_service_handle)))
|
| - LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
|
| -
|
| - // Ensure that the validation cache key (used as an extra input to the
|
| - // validation cache's hashing) isn't exposed accidentally.
|
| - CHECK(!params.validation_cache_enabled);
|
| - CHECK(params.validation_cache_key.size() == 0);
|
| - CHECK(params.version.size() == 0);
|
| - // Ensure that a debug stub FD isn't passed through accidentally.
|
| - CHECK(!params.enable_debug_stub);
|
| - CHECK(params.debug_stub_server_bound_socket.fd == -1);
|
| -
|
| - CHECK(!params.uses_irt);
|
| - CHECK(params.handles.empty());
|
| -
|
| - CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit());
|
| - CHECK(params.nexe_token_lo == 0);
|
| - CHECK(params.nexe_token_hi == 0);
|
| - nacl::nonsfi::MainStart(
|
| - IPC::PlatformFileForTransitToPlatformFile(params.nexe_file));
|
| -#endif // defined(OS_LINUX)
|
| -}
|
| -
|
| -IPC::ChannelHandle NaClListener::CreateTrustedListener(
|
| - base::MessageLoopProxy* message_loop_proxy,
|
| - base::WaitableEvent* shutdown_event) {
|
| - // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl".
|
| - // Using an alternate channel name prevents the pipe from being created on
|
| - // Windows when the sandbox is enabled.
|
| - IPC::ChannelHandle trusted_renderer_handle =
|
| - IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| - trusted_listener_ = new NaClTrustedListener(
|
| - trusted_renderer_handle, io_thread_.message_loop_proxy().get());
|
| -#if defined(OS_POSIX)
|
| - trusted_renderer_handle.socket = base::FileDescriptor(
|
| - trusted_listener_->TakeClientFileDescriptor(), true);
|
| -#endif
|
| - return trusted_renderer_handle;
|
| -}
|
| +} // namespace nacl
|
|
|