diff options
author | ncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-27 00:16:47 +0000 |
---|---|---|
committer | ncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-27 00:16:47 +0000 |
commit | 43866cd42bd433961d3b631ebbd9afe2ae85699f (patch) | |
tree | dec64d88f0f35f8e00a0b2850d614016b4024381 /chrome/nacl | |
parent | 000b98ddf1aca041c77865d1ba8968577a1efa35 (diff) | |
download | chromium_src-43866cd42bd433961d3b631ebbd9afe2ae85699f.zip chromium_src-43866cd42bd433961d3b631ebbd9afe2ae85699f.tar.gz chromium_src-43866cd42bd433961d3b631ebbd9afe2ae85699f.tar.bz2 |
Create a database for NaCl validation caching that is shared between processes.
This change primarily entails creating a SyncChannel between sel_ldr and the
browser. Queries to the database could be made from any thread inside sel_ldr,
so the query mechanism needs to be thread safe.
This feature is currently disabled by default, and requires an environment
variable to enable. A few changes need to be made before this features is safe
and can be enabled, such as making sure each installation has a unique,
crypographically secure key.
BUG= http://code.google.com/p/nativeclient/issues/detail?id=2515
TEST= Run NaCl w/ NACL_VALIDATION_CACHE=1
Review URL: http://codereview.chromium.org/9796006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129061 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/nacl')
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 91 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.h | 22 |
2 files changed, 107 insertions, 6 deletions
diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index d4a4717..0500a85 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -5,13 +5,17 @@ #include "chrome/nacl/nacl_listener.h" #include <errno.h> +#include <stdlib.h> #include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "chrome/common/nacl_messages.h" -#include "ipc/ipc_channel.h" +#include "chrome/nacl/nacl_validation_db.h" +#include "chrome/nacl/nacl_validation_query.h" +#include "ipc/ipc_sync_channel.h" +#include "ipc/ipc_sync_message_filter.h" #include "ipc/ipc_switches.h" #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" @@ -64,19 +68,85 @@ int CreateMemoryObject(size_t size, int executable) { } #endif + +// Use an env var because command line args are eaten by nacl_helper. +bool CheckEnvVar(const char* name, bool default_value) { + bool result = default_value; + const char* var = getenv(name); + if (var && strlen(var) > 0) { + result = var[0] != '0'; + } + return result; +} + } // namespace -NaClListener::NaClListener() : debug_enabled_(false) {} +class BrowserValidationDBProxy : public NaClValidationDB { + public: + explicit BrowserValidationDBProxy(NaClListener* listener) + : listener_(listener) { + } + + bool QueryKnownToValidate(const std::string& signature) { + // Initialize to false so that if the Send fails to write to the return + // value we're safe. For example if the message is (for some reason) + // dispatched as an async message the return parameter will not be written. + bool result = false; + if (!listener_->Send(new NaClProcessMsg_QueryKnownToValidate(signature, + &result))) { + LOG(ERROR) << "Failed to query NaCl validation cache."; + result = false; + } + return result; + } + + void SetKnownToValidate(const std::string& signature) { + // Caching is optional: NaCl will still work correctly if the IPC fails. + if (!listener_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) { + LOG(ERROR) << "Failed to update NaCl validation cache."; + } + } + + private: + // The listener never dies, otherwise this might be a dangling reference. + NaClListener* listener_; +}; + + +NaClListener::NaClListener() : shutdown_event_(true, false), + io_thread_("NaCl_IOThread"), + main_loop_(NULL), + debug_enabled_(false) { + io_thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); +} -NaClListener::~NaClListener() {} +NaClListener::~NaClListener() { + NOTREACHED(); + shutdown_event_.Signal(); +} + +bool NaClListener::Send(IPC::Message* msg) { + DCHECK(main_loop_ != NULL); + if (MessageLoop::current() == main_loop_) { + // This thread owns the channel. + return channel_->Send(msg); + } else { + // This thread does not own the channel. + return filter_->Send(msg); + } +} void NaClListener::Listen() { std::string channel_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kProcessChannelID); - IPC::Channel channel(channel_name, IPC::Channel::MODE_CLIENT, this); - CHECK(channel.Connect()); - MessageLoop::current()->Run(); + channel_.reset(new IPC::SyncChannel(this, io_thread_.message_loop_proxy(), + &shutdown_event_)); + filter_.reset(new IPC::SyncMessageFilter(&shutdown_event_)); + channel_->AddFilter(filter_.get()); + channel_->Init(channel_name, IPC::Channel::MODE_CLIENT, true); + main_loop_ = MessageLoop::current(); + main_loop_->Run(); } bool NaClListener::OnMessageReceived(const IPC::Message& msg) { @@ -120,6 +190,15 @@ void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles, args->irt_fd = irt_handle; #endif + if (CheckEnvVar("NACL_VALIDATION_CACHE", false)) { + LOG(INFO) << "NaCl validation cache enabled."; + // The cache structure is not freed and exists until the NaCl process exits. + args->validation_cache = CreateValidationCache( + new BrowserValidationDBProxy(this), + // TODO(ncbray) plumb through real keys and versions. + "bogus key for HMAC....", "bogus version"); + } + CHECK(handles.size() == 1); args->imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]); args->enable_exception_handling = enable_exception_handling; diff --git a/chrome/nacl/nacl_listener.h b/chrome/nacl/nacl_listener.h index 2738d7b..2b8bb21 100644 --- a/chrome/nacl/nacl_listener.h +++ b/chrome/nacl/nacl_listener.h @@ -8,9 +8,17 @@ #include <vector> +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" #include "chrome/common/nacl_types.h" #include "ipc/ipc_channel.h" +namespace IPC { +class SyncChannel; +class SyncMessageFilter; +} + // The NaClListener is an IPC channel listener that waits for a // request to start a NaCl module. class NaClListener : public IPC::Channel::Listener { @@ -21,11 +29,25 @@ class NaClListener : public IPC::Channel::Listener { void Listen(); void set_debug_enabled(bool value) {debug_enabled_ = value;} + bool Send(IPC::Message* msg); + private: void OnStartSelLdr(std::vector<nacl::FileDescriptor> handles, bool enable_exception_handling); virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + // A channel back to the browser. + scoped_ptr<IPC::SyncChannel> channel_; + + // A filter that allows other threads to use the channel. + scoped_ptr<IPC::SyncMessageFilter> filter_; + + base::WaitableEvent shutdown_event_; + base::Thread io_thread_; + + // Used to identify what thread we're on. + MessageLoop* main_loop_; + bool debug_enabled_; DISALLOW_COPY_AND_ASSIGN(NaClListener); |