summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/nacl/browser/nacl_host_message_filter.cc4
-rw-r--r--components/nacl/browser/nacl_process_host.cc30
-rw-r--r--components/nacl/loader/nacl_ipc_adapter.cc33
-rw-r--r--components/nacl/loader/nacl_ipc_adapter.h24
-rw-r--r--components/nacl/loader/nacl_listener.cc55
-rw-r--r--components/nacl/loader/nacl_listener.h15
-rw-r--r--components/nacl/renderer/ppb_nacl_private_impl.cc2
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);