diff options
author | ncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-25 14:10:09 +0000 |
---|---|---|
committer | ncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-25 14:10:09 +0000 |
commit | 8adc12577f8f982a13411594c6a7a16c9697e37d (patch) | |
tree | 405c7345a70f180d0fc8281608c64a7c79e14fb5 /chrome | |
parent | 5816c3af91eeeefbdea545a7c3d111fe621abe45 (diff) | |
download | chromium_src-8adc12577f8f982a13411594c6a7a16c9697e37d.zip chromium_src-8adc12577f8f982a13411594c6a7a16c9697e37d.tar.gz chromium_src-8adc12577f8f982a13411594c6a7a16c9697e37d.tar.bz2 |
NaCl: enable meta-based validation for shared libraries.
This is the Chrome-side half of a CL to allow mmaping and skipping validation
for chrome-extension: files we have seen before and know are safe. To do this
we need to know the path of the file on disk, but we don't entirely trust the
renderer not to tamper with it. To work around this, a nonce is passed along
with the file handle. This nonce can be used by the NaCl process to acquire the
file handle directly from the browser process, as well as a fresh copy of the
file handle.
This change significantly revises the OpenNaClExecutable method of the
PPB_NaCl_Private interface. The method was added anticipation of this CL, but
the overall design shifted after the method was added.
BUG=https://code.google.com/p/chromium/issues/detail?id=224434
Review URL: https://chromiumcodereview.appspot.com/14750007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202278 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/nacl_host/nacl_browser.cc | 81 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_browser.h | 39 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_file_host.cc | 66 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 83 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.h | 5 | ||||
-rw-r--r-- | chrome/common/nacl_messages.h | 10 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 7 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 33 | ||||
-rw-r--r-- | chrome/nacl/nacl_validation_db.h | 4 | ||||
-rw-r--r-- | chrome/nacl/nacl_validation_query.cc | 28 | ||||
-rw-r--r-- | chrome/nacl/nacl_validation_query.h | 4 | ||||
-rw-r--r-- | chrome/nacl/nacl_validation_query_unittest.cc | 7 | ||||
-rw-r--r-- | chrome/renderer/pepper/ppb_nacl_private_impl.cc | 14 |
13 files changed, 340 insertions, 41 deletions
diff --git a/chrome/browser/nacl_host/nacl_browser.cc b/chrome/browser/nacl_host/nacl_browser.cc index d05d42e..9908f1d 100644 --- a/chrome/browser/nacl_host/nacl_browser.cc +++ b/chrome/browser/nacl_host/nacl_browser.cc @@ -10,6 +10,7 @@ #include "base/metrics/histogram.h" #include "base/path_service.h" #include "base/pickle.h" +#include "base/rand_util.h" #include "base/strings/string_split.h" #include "base/win/windows_version.h" #include "build/build_config.h" @@ -36,6 +37,16 @@ enum ValidationCacheStatus { CACHE_MAX }; +// Keep the cache bounded to an arbitrary size. If it's too small, useful +// entries could be evicted when multiple .nexes are loaded at once. On the +// other hand, entries are not always claimed (and hence removed), so the size +// of the cache will likely saturate at its maximum size. +// Entries may not be claimed for two main reasons. 1) the NaCl process could +// be killed while it is loading. 2) the trusted NaCl plugin opens files using +// the code path but doesn't resolve them. +// TODO(ncbray) don't cache files that the plugin will not resolve. +const int kFilePathCacheSize = 100; + const base::FilePath::StringType NaClIrtName() { base::FilePath::StringType irt_name(FILE_PATH_LITERAL("nacl_irt_")); @@ -106,6 +117,40 @@ void LogCacheSet(ValidationCacheStatus status) { } // namespace +namespace nacl { + +void OpenNaClExecutableImpl(const base::FilePath& file_path, + base::PlatformFile* file) { + // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to + // memory map the executable. + // IMPORTANT: This file descriptor must not have write access - that could + // allow a NaCl inner sandbox escape. + base::PlatformFileError error_code; + *file = base::CreatePlatformFile( + file_path, + (base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_EXECUTE), // Windows only flag. + NULL, + &error_code); + if (error_code != base::PLATFORM_FILE_OK) { + *file = base::kInvalidPlatformFileValue; + return; + } + // Check that the file does not reference a directory. Returning a descriptor + // to an extension directory could allow an outer sandbox escape. openat(...) + // could be used to traverse into the file system. + base::PlatformFileInfo file_info; + if (!base::GetPlatformFileInfo(*file, &file_info) || + file_info.is_directory) { + base::ClosePlatformFile(*file); + *file = base::kInvalidPlatformFileValue; + return; + } +} + +} + NaClBrowser::NaClBrowser() : weak_factory_(this), irt_platform_file_(base::kInvalidPlatformFileValue), @@ -119,6 +164,7 @@ NaClBrowser::NaClBrowser() kValidationCacheEnabledByDefault)), validation_cache_is_modified_(false), validation_cache_state_(NaClResourceUninitialized), + path_cache_(kFilePathCacheSize), ok_(true) { InitIrtFilePath(); InitValidationCacheFilePath(); @@ -372,6 +418,41 @@ const base::FilePath& NaClBrowser::GetIrtFilePath() { return irt_filepath_; } +void NaClBrowser::PutFilePath(const base::FilePath& path, uint64* file_token_lo, + uint64* file_token_hi) { + while (true) { + uint64 file_token[2] = {base::RandUint64(), base::RandUint64()}; + // A zero file_token indicates there is no file_token, if we get zero, ask + // for another number. + if (file_token[0] != 0 || file_token[1] != 0) { + // If the file_token is in use, ask for another number. + std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); + PathCacheType::iterator iter = path_cache_.Peek(key); + if (iter == path_cache_.end()) { + path_cache_.Put(key, path); + *file_token_lo = file_token[0]; + *file_token_hi = file_token[1]; + break; + } + } + } +} + +bool NaClBrowser::GetFilePath(uint64 file_token_lo, uint64 file_token_hi, + base::FilePath* path) { + uint64 file_token[2] = {file_token_lo, file_token_hi}; + std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); + PathCacheType::iterator iter = path_cache_.Peek(key); + if (iter == path_cache_.end()) { + *path = base::FilePath(FILE_PATH_LITERAL("")); + return false; + } + *path = iter->second; + path_cache_.Erase(iter); + return true; +} + + bool NaClBrowser::QueryKnownToValidate(const std::string& signature, bool off_the_record) { if (off_the_record) { diff --git a/chrome/browser/nacl_host/nacl_browser.h b/chrome/browser/nacl_host/nacl_browser.h index f3d8646..e2f041e 100644 --- a/chrome/browser/nacl_host/nacl_browser.h +++ b/chrome/browser/nacl_host/nacl_browser.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_NACL_HOST_NACL_BROWSER_H_ #include "base/bind.h" +#include "base/containers/mru_cache.h" #include "base/files/file_util_proxy.h" #include "base/memory/singleton.h" #include "base/memory/weak_ptr.h" @@ -15,6 +16,15 @@ class URLPattern; class GURL; +namespace nacl { + +// Open an immutable executable file that can be mmapped. +// This function should only be called on a thread that can perform file IO. +void OpenNaClExecutableImpl(const base::FilePath& file_path, + base::PlatformFile* file); + +} + // Represents shared state for all NaClProcessHost objects in the browser. class NaClBrowser { public: @@ -70,6 +80,32 @@ class NaClBrowser { return validation_cache_.GetValidationCacheKey(); } + // The NaCl singleton keeps information about NaCl executable files opened via + // PPAPI. This allows the NaCl process to get trusted information about the + // file directly from the browser process. In theory, a compromised renderer + // could provide a writable file handle or lie about the file's path. If we + // trusted the handle was read only but it was not, an mmapped file could be + // modified after validation, allowing an escape from the NaCl sandbox. + // Similarly, if we trusted the file path corresponded to the file handle but + // it did not, the validation cache could be tricked into bypassing validation + // for bad code. + // Instead of allowing these attacks, the NaCl process only trusts information + // it gets directly from the browser process. Because the information is + // stored in a cache of bounded size, it is not guaranteed the browser process + // will be able to provide the requested information. In these cases, the + // NaCl process must make conservative assumptions about the origin of the + // file. + // In theory, a compromised renderer could guess file tokens in an attempt to + // read files it normally doesn't have access to. This would not compromise + // the NaCl sandbox, however, and only has a 1 in ~2**120 chance of success + // per guess. + // TODO(ncbray): move the cache onto NaClProcessHost so that we don't need to + // rely on tokens being unguessable by another process. + void PutFilePath(const base::FilePath& path, uint64* file_token_lo, + uint64* file_token_hi); + bool GetFilePath(uint64 file_token_lo, uint64 file_token_hi, + base::FilePath* path); + bool QueryKnownToValidate(const std::string& signature, bool off_the_record); void SetKnownToValidate(const std::string& signature, bool off_the_record); void ClearValidationCache(const base::Closure& callback); @@ -123,6 +159,9 @@ class NaClBrowser { NaClResourceState validation_cache_state_; base::Callback<void(int)> debug_stub_port_listener_; + typedef base::HashingMRUCache<std::string, base::FilePath> PathCacheType; + PathCacheType path_cache_; + bool ok_; // A list of pending tasks to start NaCl processes. diff --git a/chrome/browser/nacl_host/nacl_file_host.cc b/chrome/browser/nacl_host/nacl_file_host.cc index 7cb61e6..16015ca 100644 --- a/chrome/browser/nacl_host/nacl_file_host.cc +++ b/chrome/browser/nacl_host/nacl_file_host.cc @@ -12,6 +12,7 @@ #include "base/threading/sequenced_worker_pool.h" #include "base/utf_string_conversions.h" #include "chrome/browser/extensions/extension_info_map.h" +#include "chrome/browser/nacl_host/nacl_browser.h" #include "chrome/browser/renderer_host/chrome_render_message_filter.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/manifest_handlers/shared_module_info.h" @@ -128,6 +129,29 @@ void DoCreateTemporaryFile( chrome_render_message_filter->Send(reply_msg); } +void DoRegisterOpenedNaClExecutableFile( + scoped_refptr<ChromeRenderMessageFilter> chrome_render_message_filter, + base::PlatformFile file, + base::FilePath file_path, + IPC::Message* reply_msg) { + // IO thread owns the NaClBrowser singleton. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); + uint64_t file_token_lo = 0; + uint64_t file_token_hi = 0; + nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); + + IPC::PlatformFileForTransit file_desc = IPC::GetFileHandleForProcess( + file, + chrome_render_message_filter->peer_handle(), + true /* close_source */); + + ChromeViewHostMsg_OpenNaClExecutable::WriteReplyParams( + reply_msg, file_desc, file_token_lo, file_token_hi); + chrome_render_message_filter->Send(reply_msg); +} + // Convert the file URL into a file path in the extension directory. // This function is security sensitive. Be sure to check with a security // person before you modify it. @@ -194,39 +218,21 @@ void DoOpenNaClExecutableOnThreadPool( return; } - // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to - // memory map the executable. - // IMPORTANT: This file descriptor must not have write access - that could - // allow a sandbox escape. - base::PlatformFileError error_code; - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN | - base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_EXECUTE, // Windows only flag. - NULL, - &error_code); - if (error_code != base::PLATFORM_FILE_OK) { - NotifyRendererOfError(chrome_render_message_filter, reply_msg); - return; - } - // Check that the file does not reference a directory. Returning a descriptor - // to an extension directory could allow a sandbox escape. - base::PlatformFileInfo file_info; - if (!base::GetPlatformFileInfo(file, &file_info) || file_info.is_directory) - { + base::PlatformFile file; + nacl::OpenNaClExecutableImpl(file_path, &file); + if (file != base::kInvalidPlatformFileValue) { + // This function is running on the blocking pool, but the path needs to be + // registered in a structure owned by the IO thread. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind( + &DoRegisterOpenedNaClExecutableFile, + chrome_render_message_filter, + file, file_path, reply_msg)); + } else { NotifyRendererOfError(chrome_render_message_filter, reply_msg); return; } - - IPC::PlatformFileForTransit file_desc = IPC::GetFileHandleForProcess( - file, - chrome_render_message_filter->peer_handle(), - true /* close_source */); - - ChromeViewHostMsg_OpenNaClExecutable::WriteReplyParams( - reply_msg, file_path, file_desc); - chrome_render_message_filter->Send(reply_msg); } } // namespace diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index a2f383e..3cac2b74 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -619,6 +619,8 @@ bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { OnQueryKnownToValidate) IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, OnSetKnownToValidate) + IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_ResolveFileToken, + OnResolveFileToken) #if defined(OS_WIN) IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_AttachDebugExceptionHandler, OnAttachDebugExceptionHandler) @@ -757,7 +759,6 @@ bool NaClProcessHost::StartNaClExecution() { if (params.uses_irt) { base::PlatformFile irt_file = nacl_browser->IrtFile(); CHECK_NE(irt_file, base::kInvalidPlatformFileValue); - // Send over the IRT file handle. We don't close our own copy! if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) return false; @@ -926,6 +927,86 @@ void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { NaClBrowser::GetInstance()->SetKnownToValidate(signature, off_the_record_); } +void NaClProcessHost::FileResolved( + base::PlatformFile* file, + const base::FilePath& file_path, + IPC::Message* reply_msg) { + if (*file != base::kInvalidPlatformFileValue) { + IPC::PlatformFileForTransit handle = IPC::GetFileHandleForProcess( + *file, + process_->GetData().handle, + true /* close_source */); + NaClProcessMsg_ResolveFileToken::WriteReplyParams( + reply_msg, + handle, + file_path); + } else { + NaClProcessMsg_ResolveFileToken::WriteReplyParams( + reply_msg, + IPC::InvalidPlatformFileForTransit(), + base::FilePath(FILE_PATH_LITERAL(""))); + } + Send(reply_msg); +} + +void NaClProcessHost::OnResolveFileToken(uint64 file_token_lo, + uint64 file_token_hi, + IPC::Message* reply_msg) { + // Was the file registered? + // + // Note that the file path cache is of bounded size, and old entries can get + // evicted. If a large number of NaCl modules are being launched at once, + // resolving the file_token may fail because the path cache was thrashed + // while the file_token was in flight. In this case the query fails, and we + // need to fall back to the slower path. + // + // However: each NaCl process will consume 2-3 entries as it starts up, this + // means that eviction will not happen unless you start up 33+ NaCl processes + // at the same time, and this still requires worst-case timing. As a + // practical matter, no entries should be evicted prematurely. + // The cache itself should take ~ (150 characters * 2 bytes/char + ~60 bytes + // data structure overhead) * 100 = 35k when full, so making it bigger should + // not be a problem, if needed. + // + // Each NaCl process will consume 2-3 entries because the manifest and main + // nexe are currently not resolved. Shared libraries will be resolved. They + // will be loaded sequentially, so they will only consume a single entry + // while the load is in flight. + // + // TODO(ncbray): track behavior with UMA. If entries are getting evicted or + // bogus keys are getting queried, this would be good to know. + base::FilePath file_path; + if (!NaClBrowser::GetInstance()->GetFilePath(file_token_lo, file_token_hi, + &file_path)) { + NaClProcessMsg_ResolveFileToken::WriteReplyParams( + reply_msg, + IPC::InvalidPlatformFileForTransit(), + base::FilePath(FILE_PATH_LITERAL(""))); + Send(reply_msg); + return; + } + + // Scratch space to share between the callbacks. + base::PlatformFile* data = new base::PlatformFile(); + + // Open the file. + if (!content::BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, + base::Bind(nacl::OpenNaClExecutableImpl, + file_path, data), + base::Bind(&NaClProcessHost::FileResolved, + weak_factory_.GetWeakPtr(), + base::Owned(data), + file_path, + reply_msg))) { + NaClProcessMsg_ResolveFileToken::WriteReplyParams( + reply_msg, + IPC::InvalidPlatformFileForTransit(), + base::FilePath(FILE_PATH_LITERAL(""))); + Send(reply_msg); + } +} + #if defined(OS_WIN) void NaClProcessHost::OnAttachDebugExceptionHandler(const std::string& info, IPC::Message* reply_msg) { diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h index 584dc9a..813890f 100644 --- a/chrome/browser/nacl_host/nacl_process_host.h +++ b/chrome/browser/nacl_host/nacl_process_host.h @@ -146,6 +146,11 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { // Message handlers for validation caching. void OnQueryKnownToValidate(const std::string& signature, bool* result); void OnSetKnownToValidate(const std::string& signature); + void OnResolveFileToken(uint64 file_token_lo, uint64 file_token_hi, + IPC::Message* reply_msg); + void FileResolved(base::PlatformFile* file, const base::FilePath& file_path, + IPC::Message* reply_msg); + #if defined(OS_WIN) // Message handler for Windows hardware exception handling. void OnAttachDebugExceptionHandler(const std::string& info, diff --git a/chrome/common/nacl_messages.h b/chrome/common/nacl_messages.h index acafe7e..f37ca83 100644 --- a/chrome/common/nacl_messages.h +++ b/chrome/common/nacl_messages.h @@ -9,6 +9,7 @@ #include "chrome/common/nacl_types.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" +#include "ipc/ipc_platform_file.h" #define IPC_MESSAGE_START NaClMsgStart @@ -78,6 +79,15 @@ IPC_SYNC_MESSAGE_CONTROL1_1(NaClProcessMsg_QueryKnownToValidate, IPC_MESSAGE_CONTROL1(NaClProcessMsg_SetKnownToValidate, std::string /* A validation signature */) +// Used by the NaCl process to acquire trusted information about a file directly +// from the browser, including the file's path as well as a fresh version of the +// file handle. +IPC_SYNC_MESSAGE_CONTROL2_2(NaClProcessMsg_ResolveFileToken, + uint64, /* file_token_lo */ + uint64, /* file_token_hi */ + IPC::PlatformFileForTransit, /* fd */ + base::FilePath /* Path opened to get fd */) + // Notify the browser process that the server side of the PPAPI channel was // created successfully. IPC_MESSAGE_CONTROL1(NaClProcessHostMsg_PpapiChannelCreated, diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 5a946e3..366394a 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -614,11 +614,12 @@ IPC_MESSAGE_CONTROL2(ChromeViewHostMsg_NaClErrorStatus, // A renderer sends this to the browser process when it wants to // open a NaCl executable file from an installed application directory. -IPC_SYNC_MESSAGE_CONTROL2_2(ChromeViewHostMsg_OpenNaClExecutable, +IPC_SYNC_MESSAGE_CONTROL2_3(ChromeViewHostMsg_OpenNaClExecutable, int /* render_view_id */, GURL /* URL of NaCl executable file */, - base::FilePath /* absolute path to opened file */, - IPC::PlatformFileForTransit /* output file */) + IPC::PlatformFileForTransit /* output file */, + uint64_t /* file_token_lo */, + uint64_t /* file_token_hi */) // Notification that the page has an OpenSearch description document // associated with it. diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index b0b27e9..d70ecd1 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -21,6 +21,7 @@ #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" +#include "native_client/src/trusted/validator/nacl_file_info.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" @@ -130,6 +131,38 @@ class BrowserValidationDBProxy : public NaClValidationDB { } } + virtual bool ResolveFileToken(struct NaClFileToken* file_token, + int32* fd, std::string* path) OVERRIDE { + *fd = -1; + *path = ""; + if (file_token->lo == 0 && file_token->hi == 0) { + return false; + } + IPC::PlatformFileForTransit ipc_fd; + base::FilePath ipc_path; + if (!listener_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo, + file_token->hi, + &ipc_fd, + &ipc_path))) { + return false; + } + if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { + return false; + } + base::PlatformFile handle = + IPC::PlatformFileForTransitToPlatformFile(ipc_fd); +#if defined(OS_WIN) + // On Windows, valid handles are 32 bit unsigned integers so this is safe. + *fd = reinterpret_cast<uintptr_t>(handle); +#else + *fd = handle; +#endif + // It doesn't matter if the path is invalid UTF8 as long as it's consistent + // and unforgeable. + *path = ipc_path.AsUTF8Unsafe(); + return true; + } + private: // The listener never dies, otherwise this might be a dangling reference. NaClListener* listener_; diff --git a/chrome/nacl/nacl_validation_db.h b/chrome/nacl/nacl_validation_db.h index c4fabcb..81351d22 100644 --- a/chrome/nacl/nacl_validation_db.h +++ b/chrome/nacl/nacl_validation_db.h @@ -9,6 +9,8 @@ #include "base/basictypes.h" +struct NaClFileToken; + class NaClValidationDB { public: NaClValidationDB() {} @@ -16,6 +18,8 @@ class NaClValidationDB { virtual bool QueryKnownToValidate(const std::string& signature) = 0; virtual void SetKnownToValidate(const std::string& signature) = 0; + virtual bool ResolveFileToken(struct NaClFileToken* file_token, + int32* fd, std::string* path) = 0; private: DISALLOW_COPY_AND_ASSIGN(NaClValidationDB); diff --git a/chrome/nacl/nacl_validation_query.cc b/chrome/nacl/nacl_validation_query.cc index 37d9b78..0ff831c 100644 --- a/chrome/nacl/nacl_validation_query.cc +++ b/chrome/nacl/nacl_validation_query.cc @@ -7,6 +7,8 @@ #include "base/logging.h" #include "crypto/nss_util.h" #include "chrome/nacl/nacl_validation_db.h" +#include "native_client/src/include/portability.h" +#include "native_client/src/trusted/validator/nacl_file_info.h" #include "native_client/src/trusted/validator/validation_cache.h" NaClValidationQueryContext::NaClValidationQueryContext( @@ -29,6 +31,13 @@ NaClValidationQuery* NaClValidationQueryContext::CreateQuery() { return query; } +bool NaClValidationQueryContext::ResolveFileToken( + struct NaClFileToken* file_token, + int32* fd, + std::string* path) { + return db_->ResolveFileToken(file_token, fd, path); +} + NaClValidationQuery::NaClValidationQuery(NaClValidationDB* db, const std::string& profile_key) : state_(READY), @@ -127,6 +136,24 @@ static void DestroyQuery(void* query) { delete static_cast<NaClValidationQuery*>(query); } +static int ResolveFileToken(void* handle, struct NaClFileToken* file_token, + int32* fd, char** file_path, + uint32* file_path_length) { + std::string path; + *file_path = NULL; + *file_path_length = 0; + bool ok = static_cast<NaClValidationQueryContext*>(handle)-> + ResolveFileToken(file_token, fd, &path); + if (ok) { + *file_path = static_cast<char*>(malloc(path.length() + 1)); + CHECK(*file_path); + memcpy(*file_path, path.data(), path.length()); + (*file_path)[path.length()] = 0; + *file_path_length = static_cast<uint32>(path.length()); + } + return ok; +} + struct NaClValidationCache* CreateValidationCache( NaClValidationDB* db, const std::string& profile_key, const std::string& nacl_version) { @@ -140,5 +167,6 @@ struct NaClValidationCache* CreateValidationCache( cache->QueryKnownToValidate = QueryKnownToValidate; cache->SetKnownToValidate = SetKnownToValidate; cache->DestroyQuery = DestroyQuery; + cache->ResolveFileToken = ResolveFileToken; return cache; } diff --git a/chrome/nacl/nacl_validation_query.h b/chrome/nacl/nacl_validation_query.h index fe82649..a849b81 100644 --- a/chrome/nacl/nacl_validation_query.h +++ b/chrome/nacl/nacl_validation_query.h @@ -11,6 +11,7 @@ #include "base/strings/string_piece.h" #include "crypto/hmac.h" +struct NaClFileToken; struct NaClValidationCache; class NaClValidationDB; class NaClValidationQuery; @@ -23,6 +24,9 @@ class NaClValidationQueryContext { NaClValidationQuery* CreateQuery(); + bool ResolveFileToken(struct NaClFileToken* file_token, int32* fd, + std::string* path); + private: NaClValidationDB* db_; diff --git a/chrome/nacl/nacl_validation_query_unittest.cc b/chrome/nacl/nacl_validation_query_unittest.cc index baf930d..511000d 100644 --- a/chrome/nacl/nacl_validation_query_unittest.cc +++ b/chrome/nacl/nacl_validation_query_unittest.cc @@ -67,6 +67,13 @@ class MockValidationDB : public NaClValidationDB { NaClValidationQuery::kDigestLength)); } + virtual bool ResolveFileToken(struct NaClFileToken* file_token, int32* fd, + std::string* path) OVERRIDE { + *fd = -1; + *path = ""; + return false; + } + bool did_query_; bool did_set_; bool status_; diff --git a/chrome/renderer/pepper/ppb_nacl_private_impl.cc b/chrome/renderer/pepper/ppb_nacl_private_impl.cc index 60a79ebc..dab0726 100644 --- a/chrome/renderer/pepper/ppb_nacl_private_impl.cc +++ b/chrome/renderer/pepper/ppb_nacl_private_impl.cc @@ -272,19 +272,22 @@ PP_NaClResult ReportNaClError(PP_Instance instance, PP_FileHandle OpenNaClExecutable(PP_Instance instance, const char* file_url, - PP_NaClExecutableMetadata* metadata) { + uint64_t* nonce_lo, + uint64_t* nonce_hi) { IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); IPC::Sender* sender = content::RenderThread::Get(); if (sender == NULL) sender = g_background_thread_sender.Pointer()->get(); - metadata->file_path = PP_MakeUndefined(); + *nonce_lo = 0; + *nonce_hi = 0; base::FilePath file_path; if (!sender->Send( new ChromeViewHostMsg_OpenNaClExecutable(GetRoutingID(instance), GURL(file_url), - &file_path, - &out_fd))) { + &out_fd, + nonce_lo, + nonce_hi))) { return base::kInvalidPlatformFileValue; } @@ -292,9 +295,6 @@ PP_FileHandle OpenNaClExecutable(PP_Instance instance, return base::kInvalidPlatformFileValue; } - metadata->file_path = - ppapi::StringVar::StringToPPVar(file_path.AsUTF8Unsafe()); - base::PlatformFile handle = IPC::PlatformFileForTransitToPlatformFile(out_fd); return handle; |