summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-29 00:19:27 +0000
committerncbray@chromium.org <ncbray@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-29 00:19:27 +0000
commit041834525ed2e88ecdd260f449011d778fe6cf2a (patch)
treef41851d0f9ff423856b5c9c69f72d5c9bc299de6
parent045098dbcd386e23ee9b69d9d453f5ec41cc8298 (diff)
downloadchromium_src-041834525ed2e88ecdd260f449011d778fe6cf2a.zip
chromium_src-041834525ed2e88ecdd260f449011d778fe6cf2a.tar.gz
chromium_src-041834525ed2e88ecdd260f449011d778fe6cf2a.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 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=202278 R=dmichael@chromium.org, jschuh@chromium.org, mseaborn@chromium.org Review URL: https://codereview.chromium.org/14750007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202702 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/nacl_host/nacl_browser.cc81
-rw-r--r--chrome/browser/nacl_host/nacl_browser.h39
-rw-r--r--chrome/browser/nacl_host/nacl_file_host.cc66
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.cc83
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.h5
-rw-r--r--chrome/common/nacl_messages.h10
-rw-r--r--chrome/common/render_messages.h7
-rw-r--r--chrome/nacl/nacl_listener.cc33
-rw-r--r--chrome/nacl/nacl_validation_db.h4
-rw-r--r--chrome/nacl/nacl_validation_query.cc28
-rw-r--r--chrome/nacl/nacl_validation_query.h4
-rw-r--r--chrome/nacl/nacl_validation_query_unittest.cc7
-rw-r--r--chrome/renderer/pepper/ppb_nacl_private_impl.cc14
-rw-r--r--ppapi/api/private/ppb_nacl_private.idl9
-rw-r--r--ppapi/c/private/ppb_nacl_private.h24
-rw-r--r--ppapi/native_client/src/trusted/plugin/file_downloader.cc28
-rw-r--r--ppapi/native_client/src/trusted/plugin/file_downloader.h10
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin.cc57
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin.h11
-rw-r--r--ppapi/native_client/src/trusted/plugin/service_runtime.cc42
-rw-r--r--ppapi/native_client/src/trusted/plugin/service_runtime.h11
21 files changed, 441 insertions, 132 deletions
diff --git a/chrome/browser/nacl_host/nacl_browser.cc b/chrome/browser/nacl_host/nacl_browser.cc
index fd042ae..c7be0f4 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 e67b0df..037006d 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, &params.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 eb70b97..5a0d80b 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 3b85195..f2d8db6 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;
diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl
index b1f47ce..c871178 100644
--- a/ppapi/api/private/ppb_nacl_private.idl
+++ b/ppapi/api/private/ppb_nacl_private.idl
@@ -34,12 +34,6 @@ enum PP_NaClError {
PP_NACL_MANIFEST_MISSING_ARCH = 0
};
-struct PP_NaClExecutableMetadata {
- /** File path of NaCl executable. This is created by the OpenNaClExecutableFd
- * function. It is the caller's responsiblity to release it. */
- PP_Var file_path;
-};
-
/* PPB_NaCl_Private */
interface PPB_NaCl_Private {
/* Launches NaCl's sel_ldr process. Returns PP_NACL_OK on success and
@@ -129,5 +123,6 @@ interface PPB_NaCl_Private {
*/
PP_FileHandle OpenNaClExecutable([in] PP_Instance instance,
[in] str_t file_url,
- [out] PP_NaClExecutableMetadata metadata);
+ [out] uint64_t file_token_lo,
+ [out] uint64_t file_token_hi);
};
diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h
index 8e40fd8..72b62e9 100644
--- a/ppapi/c/private/ppb_nacl_private.h
+++ b/ppapi/c/private/ppb_nacl_private.h
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-/* From private/ppb_nacl_private.idl modified Mon Apr 22 22:25:20 2013. */
+/* From private/ppb_nacl_private.idl modified Fri May 17 13:21:13 2013. */
#ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
#define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
@@ -12,7 +12,6 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_macros.h"
#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/pp_var.h"
#define PPB_NACL_PRIVATE_INTERFACE_1_0 "PPB_NaCl_Private;1.0"
#define PPB_NACL_PRIVATE_INTERFACE PPB_NACL_PRIVATE_INTERFACE_1_0
@@ -57,19 +56,6 @@ typedef enum {
*/
/**
- * @addtogroup Structs
- * @{
- */
-struct PP_NaClExecutableMetadata {
- /** File path of NaCl executable. This is created by the OpenNaClExecutableFd
- * function. It is the caller's responsiblity to release it. */
- struct PP_Var file_path;
-};
-/**
- * @}
- */
-
-/**
* @addtogroup Interfaces
* @{
*/
@@ -149,10 +135,10 @@ struct PPB_NaCl_Private_1_0 {
* corresponding to the file URL and returns a file descriptor, or an invalid
* handle on failure. |metadata| is left unchanged on failure.
*/
- PP_FileHandle (*OpenNaClExecutable)(
- PP_Instance instance,
- const char* file_url,
- struct PP_NaClExecutableMetadata* metadata);
+ PP_FileHandle (*OpenNaClExecutable)(PP_Instance instance,
+ const char* file_url,
+ uint64_t* file_token_lo,
+ uint64_t* file_token_hi);
};
typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private;
diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.cc b/ppapi/native_client/src/trusted/plugin/file_downloader.cc
index ce7fe30..17081242 100644
--- a/ppapi/native_client/src/trusted/plugin/file_downloader.cc
+++ b/ppapi/native_client/src/trusted/plugin/file_downloader.cc
@@ -5,6 +5,7 @@
#include "native_client/src/trusted/plugin/file_downloader.h"
#include <stdio.h>
+#include <string.h>
#include <string>
#include "native_client/src/include/portability_io.h"
@@ -21,8 +22,17 @@
#include "ppapi/cpp/url_response_info.h"
namespace {
+
const int32_t kExtensionUrlRequestStatusOk = 200;
const int32_t kDataUriRequestStatusOk = 0;
+
+struct NaClFileInfo NoFileInfo() {
+ struct NaClFileInfo info;
+ memset(&info, 0, sizeof(info));
+ info.desc = -1;
+ return info;
+}
+
}
namespace plugin {
@@ -145,7 +155,8 @@ bool FileDownloader::Open(
}
void FileDownloader::OpenFast(const nacl::string& url,
- PP_FileHandle file_handle) {
+ PP_FileHandle file_handle,
+ uint64_t file_token_lo, uint64_t file_token_hi) {
PLUGIN_PRINTF(("FileDownloader::OpenFast (url=%s)\n", url.c_str()));
CHECK(instance_ != NULL);
open_time_ = NaClGetTimeOfDayMicroseconds();
@@ -154,9 +165,12 @@ void FileDownloader::OpenFast(const nacl::string& url,
url_ = url;
mode_ = DOWNLOAD_NONE;
file_handle_ = file_handle;
+ file_token_.lo = file_token_lo;
+ file_token_.hi = file_token_hi;
}
-int32_t FileDownloader::GetPOSIXFileDescriptor() {
+struct NaClFileInfo FileDownloader::GetFileInfo() {
+ struct NaClFileInfo info = NoFileInfo();
int32_t file_desc = NACL_NO_FILE_DESC;
if (not_streaming() && file_handle_ != PP_kInvalidFileHandle) {
#if NACL_WINDOWS
@@ -165,13 +179,14 @@ int32_t FileDownloader::GetPOSIXFileDescriptor() {
#else
file_desc = file_handle_;
#endif
+ info.file_token = file_token_;
} else {
if (!streaming_to_file()) {
- return NACL_NO_FILE_DESC;
+ return NoFileInfo();
}
// Use the trusted interface to get the file descriptor.
if (file_io_trusted_interface_ == NULL) {
- return NACL_NO_FILE_DESC;
+ return NoFileInfo();
}
file_desc = file_io_trusted_interface_->GetOSFileDescriptor(
file_reader_.pp_resource());
@@ -183,12 +198,13 @@ int32_t FileDownloader::GetPOSIXFileDescriptor() {
if (posix_desc == -1) {
// Close the Windows HANDLE if it can't be converted.
CloseHandle(reinterpret_cast<HANDLE>(file_desc));
- return NACL_NO_FILE_DESC;
+ return NoFileInfo();
}
file_desc = posix_desc;
#endif
- return file_desc;
+ info.desc = file_desc;
+ return info;
}
int64_t FileDownloader::TimeSinceOpenMilliseconds() const {
diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.h b/ppapi/native_client/src/trusted/plugin/file_downloader.h
index a60c837..7d87930 100644
--- a/ppapi/native_client/src/trusted/plugin/file_downloader.h
+++ b/ppapi/native_client/src/trusted/plugin/file_downloader.h
@@ -10,6 +10,7 @@
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_string.h"
#include "native_client/src/trusted/plugin/callback_source.h"
+#include "native_client/src/trusted/validator/nacl_file_info.h"
#include "ppapi/c/private/pp_file_handle.h"
#include "ppapi/c/trusted/ppb_file_io_trusted.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
@@ -85,14 +86,16 @@ class FileDownloader {
StreamCallbackSource* stream_callback_source);
// Bypasses downloading and takes a handle to the open file. To get the fd,
- // call GetPOSIXFileDescriptor().
- void OpenFast(const nacl::string& url, PP_FileHandle file_handle);
+ // call GetFileInfo().
+ void OpenFast(const nacl::string& url, PP_FileHandle file_handle,
+ uint64_t file_token_lo, uint64_t file_token_hi);
+ // Return a structure describing the file opened, including a file desc.
// If downloading and opening succeeded, this returns a valid read-only
// POSIX file descriptor. On failure, the return value is an invalid
// descriptor. The file descriptor is owned by this instance, so the
// delegate does not have to close it.
- int32_t GetPOSIXFileDescriptor();
+ struct NaClFileInfo GetFileInfo();
// Returns the time delta between the call to Open() and this function.
int64_t TimeSinceOpenMilliseconds() const;
@@ -160,6 +163,7 @@ class FileDownloader {
pp::CompletionCallback file_open_notify_callback_;
pp::FileIO file_reader_;
PP_FileHandle file_handle_;
+ struct NaClFileToken file_token_;
const PPB_FileIOTrusted* file_io_trusted_interface_;
const PPB_URLLoaderTrusted* url_loader_trusted_interface_;
pp::URLLoader url_loader_;
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 34b487d..cd5dfbf 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -802,16 +802,16 @@ void Plugin::HistogramStartupTimeMedium(const std::string& name, float dt) {
void Plugin::NexeFileDidOpen(int32_t pp_error) {
PLUGIN_PRINTF(("Plugin::NexeFileDidOpen (pp_error=%"NACL_PRId32")\n",
pp_error));
- int32_t file_desc = nexe_downloader_.GetPOSIXFileDescriptor();
+ struct NaClFileInfo info = nexe_downloader_.GetFileInfo();
PLUGIN_PRINTF(("Plugin::NexeFileDidOpen (file_desc=%"NACL_PRId32")\n",
- file_desc));
+ info.desc));
HistogramHTTPStatusCode(
is_installed_ ?
"NaCl.HttpStatusCodeClass.Nexe.InstalledApp" :
"NaCl.HttpStatusCodeClass.Nexe.NotInstalledApp",
nexe_downloader_.status_code());
ErrorInfo error_info;
- if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
+ if (pp_error != PP_OK || info.desc == NACL_NO_FILE_DESC) {
if (pp_error == PP_ERROR_ABORTED) {
ReportLoadAbort();
} else if (pp_error == PP_ERROR_NOACCESS) {
@@ -824,7 +824,7 @@ void Plugin::NexeFileDidOpen(int32_t pp_error) {
}
return;
}
- int32_t file_desc_ok_to_close = DUP(file_desc);
+ int32_t file_desc_ok_to_close = DUP(info.desc);
if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
error_info.SetReport(ERROR_NEXE_FH_DUP,
"could not duplicate loaded file handle.");
@@ -1083,10 +1083,10 @@ void Plugin::NaClManifestFileDidOpen(int32_t pp_error) {
// The manifest file was successfully opened. Set the src property on the
// plugin now, so that the full url is available to error handlers.
set_manifest_url(nexe_downloader_.url());
- int32_t file_desc = nexe_downloader_.GetPOSIXFileDescriptor();
+ struct NaClFileInfo info = nexe_downloader_.GetFileInfo();
PLUGIN_PRINTF(("Plugin::NaClManifestFileDidOpen (file_desc=%"
- NACL_PRId32")\n", file_desc));
- if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
+ NACL_PRId32")\n", info.desc));
+ if (pp_error != PP_OK || info.desc == NACL_NO_FILE_DESC) {
if (pp_error == PP_ERROR_ABORTED) {
ReportLoadAbort();
} else if (pp_error == PP_ERROR_NOACCESS) {
@@ -1102,7 +1102,7 @@ void Plugin::NaClManifestFileDidOpen(int32_t pp_error) {
}
// SlurpFile closes the file descriptor after reading (or on error).
// Duplicate our file descriptor since it will be handled by the browser.
- int dup_file_desc = DUP(file_desc);
+ int dup_file_desc = DUP(info.desc);
nacl::string json_buffer;
file_utils::StatusCode status = file_utils::SlurpFile(
dup_file_desc, json_buffer, kNaClManifestMaxFileBytes);
@@ -1274,28 +1274,32 @@ void Plugin::UrlDidOpenForStreamAsFile(int32_t pp_error,
static_cast<void*>(url_downloader)));
url_downloaders_.erase(url_downloader);
nacl::scoped_ptr<FileDownloader> scoped_url_downloader(url_downloader);
- int32_t file_desc = scoped_url_downloader->GetPOSIXFileDescriptor();
+ struct NaClFileInfo info = scoped_url_downloader->GetFileInfo();
if (pp_error != PP_OK) {
PP_RunCompletionCallback(&callback, pp_error);
- } else if (file_desc > NACL_NO_FILE_DESC) {
- url_fd_map_[url_downloader->url_to_open()] = file_desc;
+ } else if (info.desc > NACL_NO_FILE_DESC) {
+ url_file_info_map_[url_downloader->url_to_open()] = info;
PP_RunCompletionCallback(&callback, PP_OK);
} else {
PP_RunCompletionCallback(&callback, PP_ERROR_FAILED);
}
}
-int32_t Plugin::GetPOSIXFileDesc(const nacl::string& url) {
- PLUGIN_PRINTF(("Plugin::GetFileDesc (url=%s)\n", url.c_str()));
- int32_t file_desc_ok_to_close = NACL_NO_FILE_DESC;
- std::map<nacl::string, int32_t>::iterator it = url_fd_map_.find(url);
- if (it != url_fd_map_.end())
- file_desc_ok_to_close = DUP(it->second);
- return file_desc_ok_to_close;
+struct NaClFileInfo Plugin::GetFileInfo(const nacl::string& url) {
+ struct NaClFileInfo info;
+ memset(&info, 0, sizeof(info));
+ std::map<nacl::string, struct NaClFileInfo>::iterator it =
+ url_file_info_map_.find(url);
+ if (it != url_file_info_map_.end()) {
+ info = it->second;
+ info.desc = DUP(info.desc);
+ } else {
+ info.desc = -1;
+ }
+ return info;
}
-
bool Plugin::StreamAsFile(const nacl::string& url,
PP_CompletionCallback callback) {
PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str()));
@@ -1574,25 +1578,18 @@ bool Plugin::OpenURLFast(const nacl::string& url,
if (!DocumentCanRequest(url))
return false;
- PP_NaClExecutableMetadata file_metadata;
+ uint64_t file_token_lo = 0;
+ uint64_t file_token_hi = 0;
PP_FileHandle file_handle =
nacl_interface()->OpenNaClExecutable(pp_instance(),
url.c_str(),
- &file_metadata);
+ &file_token_lo, &file_token_hi);
// We shouldn't hit this if the file URL is in an installed app.
if (file_handle == PP_kInvalidFileHandle)
return false;
- // Release the PP_Var in the metadata struct.
- pp::Module* module = pp::Module::Get();
- const PPB_Var* var_interface =
- static_cast<const PPB_Var*>(
- module->GetBrowserInterface(PPB_VAR_INTERFACE));
- var_interface->Release(file_metadata.file_path);
-
// FileDownloader takes ownership of the file handle.
- // TODO(bbudge) Consume metadata once we have the final format.
- downloader->OpenFast(url, file_handle);
+ downloader->OpenFast(url, file_handle, file_token_lo, file_token_hi);
return true;
}
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h
index 37bcfdd..eecddc6 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.h
+++ b/ppapi/native_client/src/trusted/plugin/plugin.h
@@ -24,6 +24,7 @@
#include "native_client/src/trusted/plugin/pnacl_coordinator.h"
#include "native_client/src/trusted/plugin/service_runtime.h"
#include "native_client/src/trusted/plugin/utility.h"
+#include "native_client/src/trusted/validator/nacl_file_info.h"
#include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/cpp/private/var_private.h"
@@ -252,9 +253,11 @@ class Plugin : public pp::InstancePrivate {
// corresponding to the url body is recorded for further lookup.
bool StreamAsFile(const nacl::string& url,
PP_CompletionCallback pp_callback);
- // Returns an open POSIX file descriptor retrieved by StreamAsFile()
- // or NACL_NO_FILE_DESC. The caller must take ownership of the descriptor.
- int32_t GetPOSIXFileDesc(const nacl::string& url);
+
+ // Returns rich information for a file retrieved by StreamAsFile(). This info
+ // contains a file descriptor. The caller must take ownership of this
+ // descriptor.
+ struct NaClFileInfo GetFileInfo(const nacl::string& url);
// A helper function that gets the scheme type for |url|. Uses URLUtil_Dev
// interface which this class has as a member.
@@ -475,7 +478,7 @@ class Plugin : public pp::InstancePrivate {
std::set<FileDownloader*> url_downloaders_;
// Keep track of file descriptors opened by StreamAsFile().
// These are owned by the browser.
- std::map<nacl::string, int32_t> url_fd_map_;
+ std::map<nacl::string, struct NaClFileInfo> url_file_info_map_;
// Pending progress events.
std::queue<ProgressEvent*> progress_events_;
diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.cc b/ppapi/native_client/src/trusted/plugin/service_runtime.cc
index ba21a49..6c44bc4 100644
--- a/ppapi/native_client/src/trusted/plugin/service_runtime.cc
+++ b/ppapi/native_client/src/trusted/plugin/service_runtime.cc
@@ -46,11 +46,10 @@
#include "native_client/src/trusted/plugin/pnacl_resources.h"
#include "native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h"
#include "native_client/src/trusted/plugin/srpc_client.h"
-
-#include "native_client/src/trusted/weak_ref/call_on_main_thread.h"
-
#include "native_client/src/trusted/service_runtime/nacl_error_code.h"
#include "native_client/src/trusted/service_runtime/include/sys/nacl_imc_api.h"
+#include "native_client/src/trusted/validator/nacl_file_info.h"
+#include "native_client/src/trusted/weak_ref/call_on_main_thread.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/trusted/ppb_file_io_trusted.h"
@@ -172,11 +171,15 @@ bool PluginReverseInterface::EnumerateManifestKeys(
// and invoke StreamAsFile with a completion callback that invokes
// GetPOSIXFileDesc.
bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key,
- int32_t* out_desc) {
+ struct NaClFileInfo* info) {
ErrorInfo error_info;
bool op_complete = false; // NB: mu_ and cv_ also controls access to this!
+ // The to_open object is owned by the weak ref callback. Because this function
+ // waits for the callback to finish, the to_open object will be deallocated on
+ // the main thread before this function can return. The pointers it contains
+ // to stack variables will not leak.
OpenManifestEntryResource* to_open =
- new OpenManifestEntryResource(url_key, out_desc,
+ new OpenManifestEntryResource(url_key, info,
&error_info, &op_complete);
CHECK(to_open != NULL);
NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n",
@@ -228,8 +231,8 @@ bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key,
NaClLog(4,
"PluginReverseInterface::OpenManifestEntry:"
" *out_desc = %d\n",
- *out_desc);
- if (*out_desc == -1) {
+ info->desc);
+ if (info->desc == -1) {
// TODO(bsy,ncbray): what else should we do with the error? This
// is a runtime error that may simply be a programming error in
// the untrusted code, or it may be something else wrong w/ the
@@ -267,7 +270,7 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
// up requesting thread -- we are done.
nacl::MutexLocker take(&mu_);
*p->op_complete_ptr = true; // done...
- *p->out_desc = -1; // but failed.
+ p->file_info->desc = -1; // but failed.
NaClXCondVarBroadcast(&cv_);
return;
}
@@ -294,7 +297,7 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
"StreamAsFile failed\n");
nacl::MutexLocker take(&mu_);
*p->op_complete_ptr = true; // done...
- *p->out_desc = -1; // but failed.
+ p->file_info->desc = -1; // but failed.
p->error_info->SetReport(ERROR_MANIFEST_OPEN,
"ServiceRuntime: StreamAsFile failed");
NaClXCondVarBroadcast(&cv_);
@@ -321,7 +324,9 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
}
nacl::MutexLocker take(&mu_);
*p->op_complete_ptr = true; // done!
- *p->out_desc = fd;
+ // TODO(ncbray): enable the fast loading and validation paths for this
+ // type of file.
+ p->file_info->desc = fd;
NaClXCondVarBroadcast(&cv_);
NaClLog(4,
"OpenManifestEntry_MainThreadContinuation: GetPnaclFd okay\n");
@@ -347,7 +352,7 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
} else {
nacl::MutexLocker take(&mu_);
*p->op_complete_ptr = true; // done...
- *p->out_desc = -1; // but failed.
+ p->file_info->desc = -1; // but failed.
p->error_info->SetReport(ERROR_PNACL_NOT_ENABLED,
"ServiceRuntime: GetPnaclFd failed -- pnacl not "
"enabled with --enable-pnacl.");
@@ -366,16 +371,17 @@ void PluginReverseInterface::StreamAsFile_MainThreadContinuation(
nacl::MutexLocker take(&mu_);
if (result == PP_OK) {
- NaClLog(4, "StreamAsFile_MainThreadContinuation: GetPOSIXFileDesc(%s)\n",
+ NaClLog(4, "StreamAsFile_MainThreadContinuation: GetFileInfo(%s)\n",
p->url.c_str());
- *p->out_desc = plugin_->GetPOSIXFileDesc(p->url);
+ *p->file_info = plugin_->GetFileInfo(p->url);
+
NaClLog(4,
"StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n",
- *p->out_desc);
+ p->file_info->desc);
} else {
NaClLog(4,
"StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n");
- *p->out_desc = -1;
+ p->file_info->desc = -1;
p->error_info->SetReport(ERROR_MANIFEST_OPEN,
"Plugin StreamAsFile failed at callback");
}
@@ -397,16 +403,16 @@ void PluginReverseInterface::BitcodeTranslate_MainThreadContinuation(
// accepts NaClDescs we can avoid this downcast.
NaClDesc* desc = pnacl_coordinator_->ReleaseTranslatedFD()->desc();
struct NaClDescIoDesc* ndiodp = (struct NaClDescIoDesc*)desc;
- *p->out_desc = ndiodp->hd->d;
+ p->file_info->desc = ndiodp->hd->d;
pnacl_coordinator_.reset(NULL);
NaClLog(4,
"BitcodeTranslate_MainThreadContinuation: PP_OK, desc %d\n",
- *p->out_desc);
+ p->file_info->desc);
} else {
NaClLog(4,
"BitcodeTranslate_MainThreadContinuation: !PP_OK, "
"setting desc -1\n");
- *p->out_desc = -1;
+ p->file_info->desc = -1;
// Error should have been reported by pnacl coordinator.
NaClLog(LOG_ERROR, "PluginReverseInterface::BitcodeTranslate error.\n");
}
diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.h b/ppapi/native_client/src/trusted/plugin/service_runtime.h
index a7eca38..6c6bced 100644
--- a/ppapi/native_client/src/trusted/plugin/service_runtime.h
+++ b/ppapi/native_client/src/trusted/plugin/service_runtime.h
@@ -27,6 +27,8 @@
#include "ppapi/c/trusted/ppb_file_io_trusted.h"
#include "ppapi/cpp/completion_callback.h"
+struct NaClFileInfo;
+
namespace nacl {
class DescWrapper;
} // namespace
@@ -63,15 +65,15 @@ struct PostMessageResource {
struct OpenManifestEntryResource {
public:
OpenManifestEntryResource(const std::string& target_url,
- int32_t* descp,
+ struct NaClFileInfo* finfo,
ErrorInfo* infop,
bool* op_complete)
: url(target_url),
- out_desc(descp),
+ file_info(finfo),
error_info(infop),
op_complete_ptr(op_complete) {}
std::string url;
- int32_t* out_desc;
+ struct NaClFileInfo* file_info;
ErrorInfo* error_info;
bool* op_complete_ptr;
};
@@ -152,7 +154,8 @@ class PluginReverseInterface: public nacl::ReverseInterface {
virtual bool EnumerateManifestKeys(std::set<nacl::string>* out_keys);
- virtual bool OpenManifestEntry(nacl::string url_key, int32_t* out_desc);
+ virtual bool OpenManifestEntry(nacl::string url_key,
+ struct NaClFileInfo *info);
virtual bool CloseManifestEntry(int32_t desc);