summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-29 10:20:49 +0000
committermseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-29 10:20:49 +0000
commitc47ec40ba81351041096fc6cfb00c98bd74b7c06 (patch)
tree5fe3445e973fac493d888df2e30d27cdc79225fe /chrome
parenta4a849608e4b1b06dc27b986c98b5e2c57f3367c (diff)
downloadchromium_src-c47ec40ba81351041096fc6cfb00c98bd74b7c06.zip
chromium_src-c47ec40ba81351041096fc6cfb00c98bd74b7c06.tar.gz
chromium_src-c47ec40ba81351041096fc6cfb00c98bd74b7c06.tar.bz2
NaCl: Allow setting up multiple sockets for subprocess instead of just one
Remove the "channel number" parameter from messages, since this is now fixed in the NaCl plugin code in sel_main_chrome.c. Replace pair_ and descriptor_ with sockets_for_renderer_ and sockets_for_sel_ldr_. NaClProcessMsg_Start: Pass an array of FDs instead of one FD. ViewHostMsg_LaunchNaCl: * Add socket count. * Return an array of FDs instead of one FD. Expose this functionality to the NaCl plugin via a new function, "launch_nacl_process_multi_fd". BUG=50626 TEST=nacl_ui_tests Review URL: http://codereview.chromium.org/2832093 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54113 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.cc136
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.h10
-rw-r--r--chrome/common/nacl_messages_internal.h5
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/nacl/nacl_thread.cc11
-rw-r--r--chrome/nacl/nacl_thread.h2
-rw-r--r--chrome/renderer/render_process_impl.cc40
7 files changed, 146 insertions, 63 deletions
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index fb844d8..8ae9637 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -25,13 +25,25 @@
#include "chrome/browser/nacl_host/nacl_broker_service_win.h"
#endif
+namespace {
+
+void SetCloseOnExec(nacl::Handle fd) {
+#if defined(OS_POSIX)
+ int flags = fcntl(fd, F_GETFD);
+ CHECK(flags != -1);
+ int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ CHECK(rc == 0);
+#endif
+}
+
+} // namespace
+
NaClProcessHost::NaClProcessHost(
ResourceDispatcherHost *resource_dispatcher_host,
const std::wstring& url)
: BrowserChildProcessHost(NACL_LOADER_PROCESS, resource_dispatcher_host),
resource_dispatcher_host_(resource_dispatcher_host),
reply_msg_(NULL),
- descriptor_(0),
running_on_wow64_(false) {
set_name(url);
#if defined(OS_WIN)
@@ -43,6 +55,13 @@ NaClProcessHost::~NaClProcessHost() {
if (!reply_msg_)
return;
+ for (size_t i = 0; i < sockets_for_renderer_.size(); i++) {
+ nacl::Close(sockets_for_renderer_[i]);
+ }
+ for (size_t i = 0; i < sockets_for_sel_ldr_.size(); i++) {
+ nacl::Close(sockets_for_sel_ldr_[i]);
+ }
+
// OnProcessLaunched didn't get called because the process couldn't launch.
// Don't keep the renderer hanging.
reply_msg_->set_reply_error();
@@ -50,20 +69,41 @@ NaClProcessHost::~NaClProcessHost() {
}
bool NaClProcessHost::Launch(ResourceMessageFilter* resource_message_filter,
- const int descriptor,
+ int socket_count,
IPC::Message* reply_msg) {
#ifdef DISABLE_NACL
NOTIMPLEMENTED() << "Native Client disabled at build time";
return false;
#else
- // Create a connected socket
- if (nacl::SocketPair(pair_) == -1)
+ // Place an arbitrary limit on the number of sockets to limit
+ // exposure in case the renderer is compromised. We can increase
+ // this if necessary.
+ if (socket_count > 8) {
return false;
+ }
+
+ // Rather than creating a socket pair in the renderer, and passing
+ // one side through the browser to sel_ldr, socket pairs are created
+ // in the browser and then passed to the renderer and sel_ldr.
+ //
+ // This is mainly for the benefit of Windows, where sockets cannot
+ // be passed in messages, but are copied via DuplicateHandle().
+ // This means the sandboxed renderer cannot send handles to the
+ // browser process.
+
+ for (int i = 0; i < socket_count; i++) {
+ nacl::Handle pair[2];
+ // Create a connected socket
+ if (nacl::SocketPair(pair) == -1)
+ return false;
+ sockets_for_renderer_.push_back(pair[0]);
+ sockets_for_sel_ldr_.push_back(pair[1]);
+ SetCloseOnExec(pair[0]);
+ SetCloseOnExec(pair[1]);
+ }
// Launch the process
- descriptor_ = descriptor;
if (!LaunchSelLdr()) {
- nacl::Close(pair_[0]);
return false;
}
@@ -129,22 +169,34 @@ void NaClProcessHost::OnChildDied() {
}
void NaClProcessHost::OnProcessLaunched() {
- nacl::FileDescriptor imc_handle;
+ std::vector<nacl::FileDescriptor> handles_for_renderer;
base::ProcessHandle nacl_process_handle;
+
+ for (size_t i = 0; i < sockets_for_renderer_.size(); i++) {
#if defined(OS_WIN)
- // Duplicate the IMC handle
- // We assume the size of imc_handle has the same size as HANDLE, so the cast
- // below is safe.
- DCHECK(sizeof(HANDLE) == sizeof(imc_handle));
- DuplicateHandle(base::GetCurrentProcessHandle(),
- reinterpret_cast<HANDLE>(pair_[0]),
- resource_message_filter_->handle(),
- reinterpret_cast<HANDLE*>(&imc_handle),
- GENERIC_READ | GENERIC_WRITE,
- FALSE,
- DUPLICATE_CLOSE_SOURCE);
+ // Copy the handle into the renderer process.
+ HANDLE handle_in_renderer;
+ DuplicateHandle(base::GetCurrentProcessHandle(),
+ reinterpret_cast<HANDLE>(sockets_for_renderer_[i]),
+ resource_message_filter_->handle(),
+ &handle_in_renderer,
+ GENERIC_READ | GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_CLOSE_SOURCE);
+ handles_for_renderer.push_back(
+ reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer));
+#else
+ // No need to dup the imc_handle - we don't pass it anywhere else so
+ // it cannot be closed.
+ nacl::FileDescriptor imc_handle;
+ imc_handle.fd = sockets_for_renderer_[i];
+ imc_handle.auto_close = true;
+ handles_for_renderer.push_back(imc_handle);
+#endif
+ }
- // Duplicate the process handle
+#if defined(OS_WIN)
+ // Copy the process handle into the renderer process.
DuplicateHandle(base::GetCurrentProcessHandle(),
handle(),
resource_message_filter_->handle(),
@@ -153,16 +205,6 @@ void NaClProcessHost::OnProcessLaunched() {
FALSE,
0);
#else
- int flags = fcntl(pair_[0], F_GETFD);
- if (flags != -1) {
- flags |= FD_CLOEXEC;
- fcntl(pair_[0], F_SETFD, flags);
- }
- // No need to dup the imc_handle - we don't pass it anywhere else so
- // it cannot be closed.
- imc_handle.fd = pair_[0];
- imc_handle.auto_close = true;
-
// We use pid as process handle on Posix
nacl_process_handle = handle();
#endif
@@ -171,30 +213,40 @@ void NaClProcessHost::OnProcessLaunched() {
base::ProcessId nacl_process_id = base::GetProcId(handle());
ViewHostMsg_LaunchNaCl::WriteReplyParams(
- reply_msg_, imc_handle, nacl_process_handle, nacl_process_id);
+ reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id);
resource_message_filter_->Send(reply_msg_);
resource_message_filter_ = NULL;
reply_msg_ = NULL;
+ sockets_for_renderer_.clear();
SendStartMessage();
}
void NaClProcessHost::SendStartMessage() {
- nacl::FileDescriptor channel;
+ std::vector<nacl::FileDescriptor> handles_for_sel_ldr;
+ for (size_t i = 0; i < sockets_for_sel_ldr_.size(); i++) {
#if defined(OS_WIN)
- if (!DuplicateHandle(GetCurrentProcess(),
- reinterpret_cast<HANDLE>(pair_[1]),
- handle(),
- reinterpret_cast<HANDLE*>(&channel),
- GENERIC_READ | GENERIC_WRITE,
- FALSE, DUPLICATE_CLOSE_SOURCE)) {
- return;
- }
+ HANDLE channel;
+ if (!DuplicateHandle(GetCurrentProcess(),
+ reinterpret_cast<HANDLE>(sockets_for_sel_ldr_[i]),
+ handle(),
+ &channel,
+ GENERIC_READ | GENERIC_WRITE,
+ FALSE, DUPLICATE_CLOSE_SOURCE)) {
+ return;
+ }
+ handles_for_sel_ldr.push_back(
+ reinterpret_cast<nacl::FileDescriptor>(channel));
#else
- channel.fd = dup(pair_[1]);
- channel.auto_close = true;
+ nacl::FileDescriptor channel;
+ channel.fd = dup(sockets_for_sel_ldr_[i]);
+ channel.auto_close = true;
+ handles_for_sel_ldr.push_back(channel);
#endif
- Send(new NaClProcessMsg_Start(descriptor_, channel));
+ }
+
+ Send(new NaClProcessMsg_Start(handles_for_sel_ldr));
+ sockets_for_sel_ldr_.clear();
}
void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index a5212de..618492a 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -29,7 +29,7 @@ class NaClProcessHost : public BrowserChildProcessHost {
// Initialize the new NaCl process, returning true on success.
bool Launch(ResourceMessageFilter* resource_message_filter,
- const int descriptor,
+ int socket_count,
IPC::Message* reply_msg);
virtual void OnMessageReceived(const IPC::Message& msg);
@@ -69,11 +69,9 @@ class NaClProcessHost : public BrowserChildProcessHost {
// The reply message to send.
IPC::Message* reply_msg_;
- // The socket pair for the NaCl process.
- nacl::Handle pair_[2];
-
- // The NaCl specific descriptor for this process.
- int descriptor_;
+ // Socket pairs for the NaCl process and renderer.
+ std::vector<nacl::Handle> sockets_for_renderer_;
+ std::vector<nacl::Handle> sockets_for_sel_ldr_;
// Windows platform flag
bool running_on_wow64_;
diff --git a/chrome/common/nacl_messages_internal.h b/chrome/common/nacl_messages_internal.h
index abde832..8d95cc7 100644
--- a/chrome/common/nacl_messages_internal.h
+++ b/chrome/common/nacl_messages_internal.h
@@ -10,9 +10,8 @@
// These are messages sent from the browser to the NaCl process.
IPC_BEGIN_MESSAGES(NaClProcess)
// Tells the NaCl process to start.
- IPC_MESSAGE_CONTROL2(NaClProcessMsg_Start,
- int /* descriptor id */,
- nacl::FileDescriptor /* handle value */)
+ IPC_MESSAGE_CONTROL1(NaClProcessMsg_Start,
+ std::vector<nacl::FileDescriptor> /* sockets */)
// Tells the NaCl broker to launch a NaCl loader process.
IPC_MESSAGE_CONTROL1(NaClProcessMsg_LaunchLoaderThroughBroker,
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index cc29e1f..2ec245e 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1409,8 +1409,9 @@ IPC_BEGIN_MESSAGES(ViewHost)
// the process and return a handle to an IMC channel.
IPC_SYNC_MESSAGE_CONTROL2_3(ViewHostMsg_LaunchNaCl,
std::wstring /* url for the NaCl module */,
- int /* channel number */,
- nacl::FileDescriptor /* imc channel handle */,
+ int /* socket count */,
+ std::vector<nacl::FileDescriptor>
+ /* imc channel handles */,
base::ProcessHandle /* NaCl process handle */,
base::ProcessId /* NaCl process id */)
diff --git a/chrome/nacl/nacl_thread.cc b/chrome/nacl/nacl_thread.cc
index 33c0195..77b78c7 100644
--- a/chrome/nacl/nacl_thread.cc
+++ b/chrome/nacl/nacl_thread.cc
@@ -36,8 +36,11 @@ void NaClThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_END_MESSAGE_MAP()
}
-void NaClThread::OnStartSelLdr(int channel_descriptor,
- nacl::FileDescriptor handle) {
- NaClHandle nacl_handle = nacl::ToNativeHandle(handle);
- NaClMainForChromium(/* handle_count= */ 1, &nacl_handle);
+void NaClThread::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) {
+ NaClHandle* array = new NaClHandle[handles.size()];
+ for (size_t i = 0; i < handles.size(); i++) {
+ array[i] = nacl::ToNativeHandle(handles[i]);
+ }
+ NaClMainForChromium(static_cast<int>(handles.size()), array);
+ delete array;
}
diff --git a/chrome/nacl/nacl_thread.h b/chrome/nacl/nacl_thread.h
index 70bfe6f..33cccae 100644
--- a/chrome/nacl/nacl_thread.h
+++ b/chrome/nacl/nacl_thread.h
@@ -22,7 +22,7 @@ class NaClThread : public ChildThread {
private:
virtual void OnControlMessageReceived(const IPC::Message& msg);
- void OnStartSelLdr(int channel_descriptor, nacl::FileDescriptor handle);
+ void OnStartSelLdr(std::vector<nacl::FileDescriptor> handles);
// TODO(gregoryd): do we need to override Cleanup as in PluginThread?
DISALLOW_COPY_AND_ASSIGN(NaClThread);
diff --git a/chrome/renderer/render_process_impl.cc b/chrome/renderer/render_process_impl.cc
index 2c12e03..5e08817 100644
--- a/chrome/renderer/render_process_impl.cc
+++ b/chrome/renderer/render_process_impl.cc
@@ -52,17 +52,45 @@ bool LaunchNaClProcess(const char* url,
int* nacl_process_id) {
// TODO(gregoryd): nacl::FileDescriptor will be soon merged with
// base::FileDescriptor
- nacl::FileDescriptor imc_descriptor;
+ std::vector<nacl::FileDescriptor> sockets;
base::ProcessHandle nacl_process;
if (!RenderThread::current()->Send(
- new ViewHostMsg_LaunchNaCl(ASCIIToWide(url),
- imc_fd,
- &imc_descriptor,
+ new ViewHostMsg_LaunchNaCl(
+ ASCIIToWide(url),
+ /* socket_count= */ 1,
+ &sockets,
&nacl_process,
reinterpret_cast<base::ProcessId*>(nacl_process_id)))) {
return false;
}
- *imc_handle = nacl::ToNativeHandle(imc_descriptor);
+ CHECK(static_cast<int>(sockets.size()) == 1);
+ *imc_handle = nacl::ToNativeHandle(sockets[0]);
+ *nacl_process_handle = nacl_process;
+ return true;
+}
+
+bool LaunchNaClProcessMultiFD(const char* alleged_url,
+ int socket_count,
+ nacl::Handle* imc_handles,
+ nacl::Handle* nacl_process_handle,
+ int* nacl_process_id) {
+ // TODO(gregoryd): nacl::FileDescriptor will be soon merged with
+ // base::FileDescriptor
+ std::vector<nacl::FileDescriptor> sockets;
+ base::ProcessHandle nacl_process;
+ if (!RenderThread::current()->Send(
+ new ViewHostMsg_LaunchNaCl(
+ ASCIIToWide(alleged_url),
+ socket_count,
+ &sockets,
+ &nacl_process,
+ reinterpret_cast<base::ProcessId*>(nacl_process_id)))) {
+ return false;
+ }
+ CHECK(static_cast<int>(sockets.size()) == socket_count);
+ for (int i = 0; i < socket_count; i++) {
+ imc_handles[i] = nacl::ToNativeHandle(sockets[i]);
+ }
*nacl_process_handle = nacl_process;
return true;
}
@@ -160,6 +188,8 @@ RenderProcessImpl::RenderProcessImpl()
std::map<std::string, uintptr_t> funcs;
funcs["launch_nacl_process"] =
reinterpret_cast<uintptr_t>(LaunchNaClProcess);
+ funcs["launch_nacl_process_multi_fd"] =
+ reinterpret_cast<uintptr_t>(LaunchNaClProcessMultiFD);
RegisterInternalNaClPlugin(funcs);
}
#endif