summaryrefslogtreecommitdiffstats
path: root/components/nacl
diff options
context:
space:
mode:
authorhidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 08:54:49 +0000
committerhidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 08:56:18 +0000
commit8b12bb8af86c39409c215e557074b0e6cbe6212f (patch)
tree3d3a8f325b4684c529479bd47ce1a73782dcfbcd /components/nacl
parent12a87df1b63f56e596d03fc9013a2a697bc57cc0 (diff)
downloadchromium_src-8b12bb8af86c39409c215e557074b0e6cbe6212f.zip
chromium_src-8b12bb8af86c39409c215e557074b0e6cbe6212f.tar.gz
chromium_src-8b12bb8af86c39409c215e557074b0e6cbe6212f.tar.bz2
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
Diffstat (limited to 'components/nacl')
-rw-r--r--components/nacl/loader/nacl_helper_linux.cc15
-rw-r--r--components/nacl/loader/nacl_listener.cc123
-rw-r--r--components/nacl/loader/nacl_listener.h11
-rw-r--r--components/nacl/loader/nacl_trusted_listener.cc19
-rw-r--r--components/nacl/loader/nacl_trusted_listener.h5
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_listener.cc150
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_listener.h53
7 files changed, 232 insertions, 144 deletions
diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc
index 8c042d0..9789199 100644
--- a/components/nacl/loader/nacl_helper_linux.cc
+++ b/components/nacl/loader/nacl_helper_linux.cc
@@ -35,6 +35,7 @@
#include "components/nacl/common/nacl_switches.h"
#include "components/nacl/loader/nacl_listener.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 "content/public/common/child_process_sandbox_support_linux.h"
#include "content/public/common/content_descriptors.h"
@@ -106,11 +107,15 @@ void BecomeNaClLoader(base::ScopedFD browser_fd,
browser_fd.release());
base::MessageLoopForIO main_message_loop;
- NaClListener listener;
- listener.set_uses_nonsfi_mode(uses_nonsfi_mode);
- listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size);
- listener.set_number_of_cores(system_info.number_of_cores);
- listener.Listen();
+ if (uses_nonsfi_mode) {
+ nacl::nonsfi::NonSfiListener listener;
+ listener.Listen();
+ } else {
+ NaClListener listener;
+ listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size);
+ listener.set_number_of_cores(system_info.number_of_cores);
+ listener.Listen();
+ }
_exit(0);
}
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc
index 433d941..d7c97ad 100644
--- a/components/nacl/loader/nacl_listener.cc
+++ b/components/nacl/loader/nacl_listener.cc
@@ -35,10 +35,7 @@
#endif
#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
#if defined(OS_WIN)
@@ -207,7 +204,6 @@ class BrowserValidationDBProxy : public NaClValidationDB {
NaClListener::NaClListener() : shutdown_event_(true, false),
io_thread_("NaCl_IOThread"),
- uses_nonsfi_mode_(false),
#if defined(OS_LINUX)
prereserved_sandbox_size_(0),
#endif
@@ -265,11 +261,6 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) {
}
void NaClListener::OnStart(const nacl::NaClStartParams& params) {
- if (uses_nonsfi_mode_) {
- StartNonSfi(params);
- return;
- }
-
#if defined(OS_LINUX) || defined(OS_MACOSX)
int urandom_fd = dup(base::GetUrandomFD());
if (urandom_fd < 0) {
@@ -303,11 +294,14 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) {
nap, NACL_CHROME_DESC_BASE + 1);
}
- IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener(
- io_thread_.message_loop_proxy(), &shutdown_event_);
+ 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_renderer_handle, IPC::ChannelHandle())))
+ browser_handle,
+ ppapi_renderer_handle,
+ trusted_listener_->TakeClientChannelHandle(),
+ IPC::ChannelHandle())))
LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
std::vector<nacl::FileDescriptor> handles = params.handles;
@@ -408,106 +402,3 @@ 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;
-}
diff --git a/components/nacl/loader/nacl_listener.h b/components/nacl/loader/nacl_listener.h
index 6ca1ec2..31a0048 100644
--- a/components/nacl/loader/nacl_listener.h
+++ b/components/nacl/loader/nacl_listener.h
@@ -34,9 +34,6 @@ class NaClListener : public IPC::Listener {
bool Send(IPC::Message* msg);
- void set_uses_nonsfi_mode(bool uses_nonsfi_mode) {
- uses_nonsfi_mode_ = uses_nonsfi_mode;
- }
#if defined(OS_LINUX)
void set_prereserved_sandbox_size(size_t prereserved_sandbox_size) {
prereserved_sandbox_size_ = prereserved_sandbox_size;
@@ -53,13 +50,6 @@ class NaClListener : public IPC::Listener {
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.
scoped_ptr<IPC::SyncChannel> channel_;
@@ -69,7 +59,6 @@ class NaClListener : public IPC::Listener {
base::WaitableEvent shutdown_event_;
base::Thread io_thread_;
- bool uses_nonsfi_mode_;
#if defined(OS_LINUX)
size_t prereserved_sandbox_size_;
#endif
diff --git a/components/nacl/loader/nacl_trusted_listener.cc b/components/nacl/loader/nacl_trusted_listener.cc
index 5f6410a..125f146 100644
--- a/components/nacl/loader/nacl_trusted_listener.cc
+++ b/components/nacl/loader/nacl_trusted_listener.cc
@@ -8,22 +8,23 @@
NaClTrustedListener::NaClTrustedListener(
const IPC::ChannelHandle& handle,
- base::SingleThreadTaskRunner* ipc_task_runner) {
- channel_proxy_ = IPC::ChannelProxy::Create(
- handle,
- IPC::Channel::MODE_SERVER,
- this,
- ipc_task_runner).Pass();
+ base::SingleThreadTaskRunner* ipc_task_runner)
+ : channel_handle_(handle),
+ channel_proxy_(IPC::ChannelProxy::Create(
+ handle, IPC::Channel::MODE_SERVER, this, ipc_task_runner)) {
}
NaClTrustedListener::~NaClTrustedListener() {
}
+IPC::ChannelHandle NaClTrustedListener::TakeClientChannelHandle() {
+ IPC::ChannelHandle handle = channel_handle_;
#if defined(OS_POSIX)
-int NaClTrustedListener::TakeClientFileDescriptor() {
- return channel_proxy_->TakeClientFileDescriptor();
-}
+ handle.socket =
+ base::FileDescriptor(channel_proxy_->TakeClientFileDescriptor(), true);
#endif
+ return handle;
+}
bool NaClTrustedListener::OnMessageReceived(const IPC::Message& msg) {
return false;
diff --git a/components/nacl/loader/nacl_trusted_listener.h b/components/nacl/loader/nacl_trusted_listener.h
index 4819e05..bb66b42 100644
--- a/components/nacl/loader/nacl_trusted_listener.h
+++ b/components/nacl/loader/nacl_trusted_listener.h
@@ -20,9 +20,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>,
NaClTrustedListener(const IPC::ChannelHandle& handle,
base::SingleThreadTaskRunner* ipc_task_runner);
-#if defined(OS_POSIX)
- int TakeClientFileDescriptor();
-#endif
+ IPC::ChannelHandle TakeClientChannelHandle();
// Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -33,6 +31,7 @@ class NaClTrustedListener : public base::RefCounted<NaClTrustedListener>,
private:
friend class base::RefCounted<NaClTrustedListener>;
virtual ~NaClTrustedListener();
+ IPC::ChannelHandle channel_handle_;
scoped_ptr<IPC::ChannelProxy> channel_proxy_;
DISALLOW_COPY_AND_ASSIGN(NaClTrustedListener);
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.cc b/components/nacl/loader/nonsfi/nonsfi_listener.cc
new file mode 100644
index 0000000..839772c
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_listener.cc
@@ -0,0 +1,150 @@
+// 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
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.h b/components/nacl/loader/nonsfi/nonsfi_listener.h
new file mode 100644
index 0000000..a2acc61
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_listener.h
@@ -0,0 +1,53 @@
+// 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_