diff options
-rw-r--r-- | components/nacl/browser/nacl_host_message_filter.cc | 4 | ||||
-rw-r--r-- | components/nacl/browser/nacl_process_host.cc | 30 | ||||
-rw-r--r-- | components/nacl/loader/nacl_ipc_adapter.cc | 33 | ||||
-rw-r--r-- | components/nacl/loader/nacl_ipc_adapter.h | 24 | ||||
-rw-r--r-- | components/nacl/loader/nacl_listener.cc | 55 | ||||
-rw-r--r-- | components/nacl/loader/nacl_listener.h | 15 | ||||
-rw-r--r-- | components/nacl/renderer/ppb_nacl_private_impl.cc | 2 |
7 files changed, 130 insertions, 33 deletions
diff --git a/components/nacl/browser/nacl_host_message_filter.cc b/components/nacl/browser/nacl_host_message_filter.cc index 4214dd5..b55eddcf 100644 --- a/components/nacl/browser/nacl_host_message_filter.cc +++ b/components/nacl/browser/nacl_host_message_filter.cc @@ -170,6 +170,9 @@ void NaClHostMessageFilter::LaunchNaClContinuation( nacl::NaClLaunchParams safe_launch_params(launch_params); safe_launch_params.resource_prefetch_request_list.clear(); + // TODO(yusukes): Fix NaClProcessHost::~NaClProcessHost() and remove the + // ifdef. +#if !defined(OS_WIN) const std::vector<NaClResourcePrefetchRequest>& original_request_list = launch_params.resource_prefetch_request_list; content::SiteInstance* site_instance = rvh->GetSiteInstance(); @@ -186,6 +189,7 @@ void NaClHostMessageFilter::LaunchNaClContinuation( safe_launch_params.resource_prefetch_request_list.push_back( original_request_list[i]); } +#endif // Process a list of resource file URLs in // |launch_params.resource_files_to_prefetch|. diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc index 55bbaf8..08bf18d 100644 --- a/components/nacl/browser/nacl_process_host.cc +++ b/components/nacl/browser/nacl_process_host.cc @@ -267,8 +267,7 @@ NaClProcessHost::~NaClProcessHost() { } // Note: this does not work on Windows, though we currently support this - // prefetching feature only on Non-SFI mode, which is supported only on - // Linux/ChromeOS, so it should be ok. + // prefetching feature only on POSIX platforms, so it should be ok. #if defined(OS_WIN) DCHECK(prefetched_resource_files_.empty()); #else @@ -871,21 +870,26 @@ bool NaClProcessHost::StartNaClExecution() { return false; } + // Pass the pre-opened resource files to the loader. We do not have to reopen + // resource files here even for SFI mode because the descriptors are not from + // a renderer. + for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { + params.prefetched_resource_files.push_back( + NaClResourcePrefetchResult( + prefetched_resource_files_[i].file, + // For the same reason as the comment below, always use an empty + // base::FilePath for non-SFI mode. + (uses_nonsfi_mode_ ? base::FilePath() : + prefetched_resource_files_[i].file_path_metadata), + prefetched_resource_files_[i].file_key)); + } + prefetched_resource_files_.clear(); + base::FilePath file_path; if (uses_nonsfi_mode_) { // Don't retrieve the file path when using nonsfi mode; there's no // validation caching in that case, so it's unnecessary work, and would // expose the file path to the plugin. - - // Pass the pre-opened resource files to the loader. For the same reason - // as above, use an empty base::FilePath. - for (size_t i = 0; i < prefetched_resource_files_.size(); ++i) { - params.prefetched_resource_files.push_back(NaClResourcePrefetchResult( - prefetched_resource_files_[i].file, - base::FilePath(), - prefetched_resource_files_[i].file_key)); - } - prefetched_resource_files_.clear(); } else { if (NaClBrowser::GetInstance()->GetFilePath(nexe_token_.lo, nexe_token_.hi, @@ -906,8 +910,6 @@ bool NaClProcessHost::StartNaClExecution() { return true; } } - // TODO(yusukes): Handle |prefetched_resource_files_| for SFI-NaCl. - DCHECK(prefetched_resource_files_.empty()); } params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(), diff --git a/components/nacl/loader/nacl_ipc_adapter.cc b/components/nacl/loader/nacl_ipc_adapter.cc index c3a4f13..61625e0 100644 --- a/components/nacl/loader/nacl_ipc_adapter.cc +++ b/components/nacl/loader/nacl_ipc_adapter.cc @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/task_runner_util.h" +#include "base/tuple.h" #include "build/build_config.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_platform_file.h" @@ -326,11 +327,13 @@ NaClIPCAdapter::IOThreadData::~IOThreadData() { NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle, base::TaskRunner* runner, - ResolveFileTokenCallback resolve_file_token_cb) + ResolveFileTokenCallback resolve_file_token_cb, + OpenResourceCallback open_resource_cb) : lock_(), cond_var_(&lock_), task_runner_(runner), resolve_file_token_cb_(resolve_file_token_cb), + open_resource_cb_(open_resource_cb), locked_data_() { io_thread_data_.channel_ = IPC::Channel::CreateServer(handle, this); // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did, @@ -504,11 +507,11 @@ bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { // arbitrary code in a plugin process. DCHECK(!resolve_file_token_cb_.is_null()); - // resolve_file_token_cb_ must be invoked from the main thread. + // resolve_file_token_cb_ must be invoked from the I/O thread. resolve_file_token_cb_.Run( token_lo, token_hi, - base::Bind(&NaClIPCAdapter::OnFileTokenResolved, + base::Bind(&NaClIPCAdapter::SaveOpenResourceMessage, this, msg)); @@ -626,9 +629,10 @@ scoped_ptr<IPC::Message> CreateOpenResourceReply( return new_msg.Pass(); } -void NaClIPCAdapter::OnFileTokenResolved(const IPC::Message& orig_msg, - IPC::PlatformFileForTransit ipc_fd, - base::FilePath file_path) { +void NaClIPCAdapter::SaveOpenResourceMessage( + const IPC::Message& orig_msg, + IPC::PlatformFileForTransit ipc_fd, + base::FilePath file_path) { // The path where an invalid ipc_fd is returned isn't currently // covered by any tests. if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { @@ -789,6 +793,23 @@ void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { DCHECK(io_thread_data_.pending_sync_msgs_.find(id) == io_thread_data_.pending_sync_msgs_.end()); + // Handle PpapiHostMsg_OpenResource locally without sending an IPC to the + // renderer when possible. + PpapiHostMsg_OpenResource::Schema::SendParam send_params; + if (!open_resource_cb_.is_null() && + message->type() == PpapiHostMsg_OpenResource::ID && + PpapiHostMsg_OpenResource::ReadSendParam(message.get(), &send_params)) { + const std::string key = get<0>(send_params); + // Both open_resource_cb_ and SaveOpenResourceMessage must be invoked + // from the I/O thread. + if (open_resource_cb_.Run( + *message.get(), key, + base::Bind(&NaClIPCAdapter::SaveOpenResourceMessage, this))) { + // The callback sent a reply to the untrusted side. + return; + } + } + if (message->is_sync()) io_thread_data_.pending_sync_msgs_[id] = message->type(); io_thread_data_.channel_->Send(message.release()); diff --git a/components/nacl/loader/nacl_ipc_adapter.h b/components/nacl/loader/nacl_ipc_adapter.h index ece964e..f8d93ff 100644 --- a/components/nacl/loader/nacl_ipc_adapter.h +++ b/components/nacl/loader/nacl_ipc_adapter.h @@ -80,6 +80,14 @@ class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, ResolveFileTokenReplyCallback)> ResolveFileTokenCallback; + typedef base::Callback<void(const IPC::Message&, + IPC::PlatformFileForTransit, + base::FilePath)> OpenResourceReplyCallback; + + typedef base::Callback<bool(const IPC::Message&, + const std::string&, // key + OpenResourceReplyCallback)> OpenResourceCallback; + // Creates an adapter, using the thread associated with the given task // runner for posting messages. In normal use, the task runner will post to // the I/O thread of the process. @@ -91,11 +99,16 @@ class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, // |resolve_file_token_cb| is an optional callback to be invoked for // resolving file tokens received from the renderer. When the file token // is resolved, the ResolveFileTokenReplyCallback passed inside the - // ResolveFileTokenCallback will be invoked. + // ResolveFileTokenCallback will be invoked. |open_resource_cb| is also an + // optional callback to be invoked for intercepting open_resource IRT calls. + // |open_resource_cb| may immediately call a OpenResourceReplyCallback + // function to send a pre-opened resource descriptor to the untrusted side. + // OpenResourceCallback returns true when OpenResourceReplyCallback is called. NaClIPCAdapter( const IPC::ChannelHandle& handle, base::TaskRunner* runner, - ResolveFileTokenCallback resolve_file_token_cb); + ResolveFileTokenCallback resolve_file_token_cb, + OpenResourceCallback open_resource_cb); // Initializes with a given channel that's already created for testing // purposes. This function will take ownership of the given channel. @@ -177,9 +190,9 @@ class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, ~NaClIPCAdapter() override; - void OnFileTokenResolved(const IPC::Message& orig_msg, - IPC::PlatformFileForTransit ipc_fd, - base::FilePath file_path); + void SaveOpenResourceMessage(const IPC::Message& orig_msg, + IPC::PlatformFileForTransit ipc_fd, + base::FilePath file_path); bool RewriteMessage(const IPC::Message& msg, uint32_t type); @@ -209,6 +222,7 @@ class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, scoped_refptr<base::TaskRunner> task_runner_; ResolveFileTokenCallback resolve_file_token_cb_; + OpenResourceCallback open_resource_cb_; // To be accessed inside of lock_ only. LockedData locked_data_; diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc index 2ebf8d2..e6a3811 100644 --- a/components/nacl/loader/nacl_listener.cc +++ b/components/nacl/loader/nacl_listener.cc @@ -146,11 +146,13 @@ void SetUpIPCAdapter( scoped_refptr<base::MessageLoopProxy> message_loop_proxy, struct NaClApp* nap, int nacl_fd, - NaClIPCAdapter::ResolveFileTokenCallback resolve_file_token_cb) { + NaClIPCAdapter::ResolveFileTokenCallback resolve_file_token_cb, + NaClIPCAdapter::OpenResourceCallback open_resource_cb) { scoped_refptr<NaClIPCAdapter> ipc_adapter( new NaClIPCAdapter(*handle, message_loop_proxy.get(), - resolve_file_token_cb)); + resolve_file_token_cb, + open_resource_cb)); ipc_adapter->ConnectChannel(); #if defined(OS_POSIX) handle->socket = @@ -279,6 +281,32 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) { return handled; } +bool NaClListener::OnOpenResource( + const IPC::Message& msg, + const std::string& key, + NaClIPCAdapter::OpenResourceReplyCallback cb) { + // This callback is executed only on |io_thread_| with NaClIPCAdapter's + // |lock_| not being held. + DCHECK(!cb.is_null()); + PrefetchedResourceFilesMap::iterator it = + prefetched_resource_files_.find(key); + + if (it != prefetched_resource_files_.end()) { + // Fast path for prefetched FDs. + IPC::PlatformFileForTransit file = it->second.first; + base::FilePath path = it->second.second; + prefetched_resource_files_.erase(it); + // A pre-opened resource descriptor is available. Run the reply callback + // and return true. + cb.Run(msg, file, path); + return true; + } + + // Return false to fall back to the slow path. Let NaClIPCAdapter issue an + // IPC to the renderer. + return false; +} + void NaClListener::OnStart(const nacl::NaClStartParams& params) { #if defined(OS_LINUX) || defined(OS_MACOSX) int urandom_fd = dup(base::GetUrandomFD()); @@ -307,6 +335,18 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { IPC::ChannelHandle ppapi_renderer_handle; IPC::ChannelHandle manifest_service_handle; + for (size_t i = 0; i < params.prefetched_resource_files.size(); ++i) { + bool result = prefetched_resource_files_.insert(std::make_pair( + params.prefetched_resource_files[i].file_key, + std::make_pair( + params.prefetched_resource_files[i].file, + params.prefetched_resource_files[i].file_path_metadata))).second; + if (!result) { + LOG(FATAL) << "Duplicated open_resource key: " + << params.prefetched_resource_files[i].file_key; + } + } + if (params.enable_ipc_proxy) { browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); @@ -317,15 +357,19 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { // communicate with the host and to initialize the IPC dispatchers. SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), nap, NACL_CHROME_DESC_BASE, - NaClIPCAdapter::ResolveFileTokenCallback()); + NaClIPCAdapter::ResolveFileTokenCallback(), + NaClIPCAdapter::OpenResourceCallback()); SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), nap, NACL_CHROME_DESC_BASE + 1, - NaClIPCAdapter::ResolveFileTokenCallback()); + NaClIPCAdapter::ResolveFileTokenCallback(), + NaClIPCAdapter::OpenResourceCallback()); SetUpIPCAdapter(&manifest_service_handle, io_thread_.message_loop_proxy(), nap, NACL_CHROME_DESC_BASE + 2, base::Bind(&NaClListener::ResolveFileToken, + base::Unretained(this)), + base::Bind(&NaClListener::OnOpenResource, base::Unretained(this))); } @@ -434,9 +478,6 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { args->nexe_desc = NaClDescCreateWithFilePathMetadata(nexe_file, file_path_str.c_str()); - // TODO(yusukes): Support pre-opening resource files. - CHECK(params.prefetched_resource_files.empty()); - int exit_status; if (!NaClChromeMainStart(nap, args, &exit_status)) NaClExit(1); diff --git a/components/nacl/loader/nacl_listener.h b/components/nacl/loader/nacl_listener.h index eccbc19..8abfafc 100644 --- a/components/nacl/loader/nacl_listener.h +++ b/components/nacl/loader/nacl_listener.h @@ -5,6 +5,7 @@ #ifndef CHROME_NACL_NACL_LISTENER_H_ #define CHROME_NACL_NACL_LISTENER_H_ +#include <map> #include <vector> #include "base/memory/scoped_ptr.h" @@ -65,6 +66,14 @@ class NaClListener : public IPC::Listener { private: bool OnMessageReceived(const IPC::Message& msg) override; + typedef base::Callback<void(const IPC::Message&, + IPC::PlatformFileForTransit, + base::FilePath)> OpenResourceReplyCallback; + + bool OnOpenResource(const IPC::Message& msg, + const std::string& key, + OpenResourceReplyCallback cb); + void OnStart(const nacl::NaClStartParams& params); // A channel back to the browser. @@ -97,6 +106,12 @@ class NaClListener : public IPC::Listener { // Used to identify what thread we're on. base::MessageLoop* main_loop_; + typedef std::map< + std::string, // manifest key + std::pair<IPC::PlatformFileForTransit, + base::FilePath> > PrefetchedResourceFilesMap; + PrefetchedResourceFilesMap prefetched_resource_files_; + DISALLOW_COPY_AND_ASSIGN(NaClListener); }; diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc index 3a3495a..1001895 100644 --- a/components/nacl/renderer/ppb_nacl_private_impl.cc +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc @@ -422,7 +422,7 @@ void LaunchSelLdr(PP_Instance instance, IPC::InvalidPlatformFileForTransit(); std::vector<NaClResourcePrefetchRequest> resource_prefetch_request_list; - if (process_type == kNativeNaClProcessType && uses_nonsfi_mode) { + if (process_type == kNativeNaClProcessType) { JsonManifest* manifest = GetJsonManifest(instance); if (manifest) { manifest->GetPrefetchableFiles(&resource_prefetch_request_list); |