diff options
author | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 10:20:49 +0000 |
---|---|---|
committer | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 10:20:49 +0000 |
commit | c47ec40ba81351041096fc6cfb00c98bd74b7c06 (patch) | |
tree | 5fe3445e973fac493d888df2e30d27cdc79225fe /chrome | |
parent | a4a849608e4b1b06dc27b986c98b5e2c57f3367c (diff) | |
download | chromium_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.cc | 136 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.h | 10 | ||||
-rw-r--r-- | chrome/common/nacl_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/nacl/nacl_thread.cc | 11 | ||||
-rw-r--r-- | chrome/nacl/nacl_thread.h | 2 | ||||
-rw-r--r-- | chrome/renderer/render_process_impl.cc | 40 |
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 |