Commit 8b12bb8a authored by hidehiko@chromium.org's avatar hidehiko@chromium.org

Refactoring: Split NaClListener into two delegated classes.

Currently, NaClListener has supports two modes, SFI and non-SFI.
As a preparation of newlib switching of non-SFI mode, this CL splits into
each delegate class, so that, we can easily build non-SFI related code
only by PNaCl toolchain.

BUG=358465
TEST=Ran trybots.
CQ_EXTRA_TRYBOTS=tryserver.chromium.linux:linux_rel_precise32

Review URL: https://codereview.chromium.org/439713002

Cr-Commit-Position: refs/heads/master@{#288271}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288271 0039d316-1c4b-4281-b951-d872f2087c98
parent 12a87df1
...@@ -283,6 +283,8 @@ ...@@ -283,6 +283,8 @@
'nacl/loader/nonsfi/irt_resource_open.cc', 'nacl/loader/nonsfi/irt_resource_open.cc',
'nacl/loader/nonsfi/irt_thread.cc', 'nacl/loader/nonsfi/irt_thread.cc',
'nacl/loader/nonsfi/irt_util.h', 'nacl/loader/nonsfi/irt_util.h',
'nacl/loader/nonsfi/nonsfi_listener.cc',
'nacl/loader/nonsfi/nonsfi_listener.h',
'nacl/loader/nonsfi/nonsfi_main.cc', 'nacl/loader/nonsfi/nonsfi_main.cc',
'nacl/loader/nonsfi/nonsfi_main.h', 'nacl/loader/nonsfi/nonsfi_main.h',
'nacl/loader/nonsfi/nonsfi_sandbox.cc', 'nacl/loader/nonsfi/nonsfi_sandbox.cc',
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "components/nacl/common/nacl_switches.h" #include "components/nacl/common/nacl_switches.h"
#include "components/nacl/loader/nacl_listener.h" #include "components/nacl/loader/nacl_listener.h"
#include "components/nacl/loader/nonsfi/irt_exception_handling.h" #include "components/nacl/loader/nonsfi/irt_exception_handling.h"
#include "components/nacl/loader/nonsfi/nonsfi_listener.h"
#include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h" #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h"
#include "content/public/common/child_process_sandbox_support_linux.h" #include "content/public/common/child_process_sandbox_support_linux.h"
#include "content/public/common/content_descriptors.h" #include "content/public/common/content_descriptors.h"
...@@ -106,11 +107,15 @@ void BecomeNaClLoader(base::ScopedFD browser_fd, ...@@ -106,11 +107,15 @@ void BecomeNaClLoader(base::ScopedFD browser_fd,
browser_fd.release()); browser_fd.release());
base::MessageLoopForIO main_message_loop; base::MessageLoopForIO main_message_loop;
if (uses_nonsfi_mode) {
nacl::nonsfi::NonSfiListener listener;
listener.Listen();
} else {
NaClListener listener; NaClListener listener;
listener.set_uses_nonsfi_mode(uses_nonsfi_mode);
listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size); listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size);
listener.set_number_of_cores(system_info.number_of_cores); listener.set_number_of_cores(system_info.number_of_cores);
listener.Listen(); listener.Listen();
}
_exit(0); _exit(0);
} }
......
...@@ -35,10 +35,7 @@ ...@@ -35,10 +35,7 @@
#endif #endif
#if defined(OS_LINUX) #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 "content/public/common/child_process_sandbox_support_linux.h"
#include "ppapi/nacl_irt/plugin_startup.h"
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -207,7 +204,6 @@ class BrowserValidationDBProxy : public NaClValidationDB { ...@@ -207,7 +204,6 @@ class BrowserValidationDBProxy : public NaClValidationDB {
NaClListener::NaClListener() : shutdown_event_(true, false), NaClListener::NaClListener() : shutdown_event_(true, false),
io_thread_("NaCl_IOThread"), io_thread_("NaCl_IOThread"),
uses_nonsfi_mode_(false),
#if defined(OS_LINUX) #if defined(OS_LINUX)
prereserved_sandbox_size_(0), prereserved_sandbox_size_(0),
#endif #endif
...@@ -265,11 +261,6 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) { ...@@ -265,11 +261,6 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) {
} }
void NaClListener::OnStart(const nacl::NaClStartParams& params) { void NaClListener::OnStart(const nacl::NaClStartParams& params) {
if (uses_nonsfi_mode_) {
StartNonSfi(params);
return;
}
#if defined(OS_LINUX) || defined(OS_MACOSX) #if defined(OS_LINUX) || defined(OS_MACOSX)
int urandom_fd = dup(base::GetUrandomFD()); int urandom_fd = dup(base::GetUrandomFD());
if (urandom_fd < 0) { if (urandom_fd < 0) {
...@@ -303,11 +294,14 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { ...@@ -303,11 +294,14 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
nap, NACL_CHROME_DESC_BASE + 1); nap, NACL_CHROME_DESC_BASE + 1);
} }
IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( trusted_listener_ = new NaClTrustedListener(
io_thread_.message_loop_proxy(), &shutdown_event_); IPC::Channel::GenerateVerifiedChannelID("nacl"),
io_thread_.message_loop_proxy().get());
if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
browser_handle, ppapi_renderer_handle, browser_handle,
trusted_renderer_handle, IPC::ChannelHandle()))) ppapi_renderer_handle,
trusted_listener_->TakeClientChannelHandle(),
IPC::ChannelHandle())))
LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
std::vector<nacl::FileDescriptor> handles = params.handles; std::vector<nacl::FileDescriptor> handles = params.handles;
...@@ -408,106 +402,3 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { ...@@ -408,106 +402,3 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
NaClChromeMainStartApp(nap, args); 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;
}
...@@ -34,9 +34,6 @@ class NaClListener : public IPC::Listener { ...@@ -34,9 +34,6 @@ class NaClListener : public IPC::Listener {
bool Send(IPC::Message* msg); bool Send(IPC::Message* msg);
void set_uses_nonsfi_mode(bool uses_nonsfi_mode) {
uses_nonsfi_mode_ = uses_nonsfi_mode;
}
#if defined(OS_LINUX) #if defined(OS_LINUX)
void set_prereserved_sandbox_size(size_t prereserved_sandbox_size) { void set_prereserved_sandbox_size(size_t prereserved_sandbox_size) {
prereserved_sandbox_size_ = prereserved_sandbox_size; prereserved_sandbox_size_ = prereserved_sandbox_size;
...@@ -53,13 +50,6 @@ class NaClListener : public IPC::Listener { ...@@ -53,13 +50,6 @@ class NaClListener : public IPC::Listener {
void OnStart(const nacl::NaClStartParams& params); void OnStart(const nacl::NaClStartParams& params);
// Non-SFI version of OnStart().
void StartNonSfi(const nacl::NaClStartParams& params);
IPC::ChannelHandle CreateTrustedListener(
base::MessageLoopProxy* message_loop_proxy,
base::WaitableEvent* shutdown_event);
// A channel back to the browser. // A channel back to the browser.
scoped_ptr<IPC::SyncChannel> channel_; scoped_ptr<IPC::SyncChannel> channel_;
...@@ -69,7 +59,6 @@ class NaClListener : public IPC::Listener { ...@@ -69,7 +59,6 @@ class NaClListener : public IPC::Listener {
base::WaitableEvent shutdown_event_; base::WaitableEvent shutdown_event_;
base::Thread io_thread_; base::Thread io_thread_;
bool uses_nonsfi_mode_;
#if defined(OS_LINUX) #if defined(OS_LINUX)
size_t prereserved_sandbox_size_; size_t prereserved_sandbox_size_;
#endif #endif
......
...@@ -8,22 +8,23 @@ ...@@ -8,22 +8,23 @@
NaClTrustedListener::NaClTrustedListener( NaClTrustedListener::NaClTrustedListener(
const IPC::ChannelHandle& handle, const IPC::ChannelHandle& handle,
base::SingleThreadTaskRunner* ipc_task_runner) { base::SingleThreadTaskRunner* ipc_task_runner)
channel_proxy_ = IPC::ChannelProxy::Create( : channel_handle_(handle),
handle, channel_proxy_(IPC::ChannelProxy::Create(
IPC::Channel::MODE_SERVER, handle, IPC::Channel::MODE_SERVER, this, ipc_task_runner)) {
this,
ipc_task_runner).Pass();
} }
NaClTrustedListener::~NaClTrustedListener() { NaClTrustedListener::~NaClTrustedListener() {
} }
IPC::ChannelHandle NaClTrustedListener::TakeClientChannelHandle() {
IPC::ChannelHandle handle = channel_handle_;
#if defined(OS_POSIX) #if defined(OS_POSIX)
int NaClTrustedListener::TakeClientFileDescriptor() { handle.socket =
return channel_proxy_->TakeClientFileDescriptor(); base::FileDescriptor(channel_proxy_->TakeClientFileDescriptor(), true);
}
#endif #endif
return handle;
}
bool NaClTrustedListener::OnMessageReceived(const IPC::Message& msg) { bool NaClTrustedListener::OnMessageReceived(const IPC::Message& msg) {
return false; return false;
......
...@@ -20,9 +20,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>, ...@@ -20,9 +20,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>,
NaClTrustedListener(const IPC::ChannelHandle& handle, NaClTrustedListener(const IPC::ChannelHandle& handle,
base::SingleThreadTaskRunner* ipc_task_runner); base::SingleThreadTaskRunner* ipc_task_runner);
#if defined(OS_POSIX) IPC::ChannelHandle TakeClientChannelHandle();
int TakeClientFileDescriptor();
#endif
// Listener implementation. // Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
...@@ -33,6 +31,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>, ...@@ -33,6 +31,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>,
private: private:
friend class base::RefCounted<NaClTrustedListener>; friend class base::RefCounted<NaClTrustedListener>;
virtual ~NaClTrustedListener(); virtual ~NaClTrustedListener();
IPC::ChannelHandle channel_handle_;
scoped_ptr<IPC::ChannelProxy> channel_proxy_; scoped_ptr<IPC::ChannelProxy> channel_proxy_;
DISALLOW_COPY_AND_ASSIGN(NaClTrustedListener); DISALLOW_COPY_AND_ASSIGN(NaClTrustedListener);
......
// 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/nonsfi/nonsfi_listener.h"
#include "base/command_line.h"
#include "base/file_descriptor_posix.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "components/nacl/common/nacl_messages.h"
#include "components/nacl/common/nacl_types.h"
#include "components/nacl/loader/nacl_trusted_listener.h"
#include "components/nacl/loader/nonsfi/irt_random.h"
#include "components/nacl/loader/nonsfi/nonsfi_main.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ppapi/nacl_irt/plugin_startup.h"
#if !defined(OS_LINUX)
# error "non-SFI mode is supported only on linux."
#endif
namespace nacl {
namespace nonsfi {
NonSfiListener::NonSfiListener() : io_thread_("NaCl_IOThread"),
shutdown_event_(true, false) {
io_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
}
NonSfiListener::~NonSfiListener() {
}
void NonSfiListener::Listen() {
channel_ = IPC::SyncChannel::Create(
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessChannelID),
IPC::Channel::MODE_CLIENT,
this, // As a Listener.
io_thread_.message_loop_proxy().get(),
true, // Create pipe now.
&shutdown_event_);
base::MessageLoop::current()->Run();
}
bool NonSfiListener::Send(IPC::Message* msg) {
DCHECK(channel_.get() != NULL);
return channel_->Send(msg);
}
bool NonSfiListener::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NonSfiListener, msg)
IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void NonSfiListener::OnStart(const nacl::NaClStartParams& params) {
// Random number source initialization.
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.
trusted_listener_ = new NaClTrustedListener(
IPC::Channel::GenerateVerifiedChannelID("nacl"),
io_thread_.message_loop_proxy().get());
if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
browser_handle,
ppapi_renderer_handle,
trusted_listener_->TakeClientChannelHandle(),
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);
MainStart(IPC::PlatformFileForTransitToPlatformFile(params.nexe_file));
}
} // namespace nonsfi
} // namespace nacl
// 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.
#ifndef COMPONENTS_NACL_LOADER_NONSFI_NONSFI_LISTENER_H_
#define COMPONENTS_NACL_LOADER_NONSFI_NONSFI_LISTENER_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "ipc/ipc_listener.h"
namespace IPC {
class Message;
class SyncChannel;
} // namespace IPC
class NaClTrustedListener;
namespace nacl {
struct NaClStartParams;
namespace nonsfi {
class NonSfiListener : public IPC::Listener {
public:
NonSfiListener();
virtual ~NonSfiListener();
// Listen for a request to launch a non-SFI NaCl module.
void Listen();
bool Send(IPC::Message* msg);
private:
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
void OnStart(const nacl::NaClStartParams& params);
base::Thread io_thread_;
base::WaitableEvent shutdown_event_;
scoped_ptr<IPC::SyncChannel> channel_;
scoped_refptr<NaClTrustedListener> trusted_listener_;
DISALLOW_COPY_AND_ASSIGN(NonSfiListener);
};
} // namespace nonsfi
} // namespace nacl
#endif // COMPONENTS_NACL_LOADER_NONSFI_NONSFI_LISTENER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment