0

Packaged (CRX) extensions shouldn't be able to get 'dev' interfaces in NaCl.BUG=100228TEST=manual

Review URL: http://codereview.chromium.org/8301006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105985 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
bbudge@google.com
2011-10-18 01:12:38 +00:00
parent c18bf248cc
commit c040e68034
9 changed files with 114 additions and 148 deletions

@ -417,54 +417,15 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD, true, true);
}
// Enforce the Chrome WebStore restriction on the Native Client plugin.
if (is_nacl_plugin) {
bool allow_nacl = cmd->HasSwitch(switches::kEnableNaCl);
if (!allow_nacl) {
const char* kNaClPluginMimeType = "application/x-nacl";
const char* kNaClPluginManifestAttribute = "nacl";
GURL nexe_url;
if (actual_mime_type == kNaClPluginMimeType) {
nexe_url = url; // Normal embedded NaCl plugin.
} else {
// Content type handling NaCl plugin; the "nacl" param on the
// MIME type holds the nexe URL.
string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute);
for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
if (plugin.mime_types[i].mime_type == actual_mime_type) {
const webkit::WebPluginMimeType& content_type =
plugin.mime_types[i];
for (size_t i = 0;
i < content_type.additional_param_names.size(); ++i) {
if (content_type.additional_param_names[i] == nacl_attr) {
nexe_url = GURL(content_type.additional_param_values[i]);
break;
}
}
break;
}
}
}
// Create the NaCl plugin only if the .nexe is part of an extension
// that was installed from the Chrome Web Store, or part of a component
// extension, or part of an unpacked extension.
const Extension* extension =
extension_dispatcher_->extensions()->GetByURL(nexe_url);
allow_nacl = extension &&
(extension->from_webstore() ||
extension->location() == Extension::COMPONENT ||
extension->location() == Extension::LOAD);
}
if (!allow_nacl) {
// TODO(bbudge) Webkit will crash if this is a full-frame plug-in and
// we return NULL. Prepare a patch to fix that, and return NULL here.
if (is_nacl_plugin &&
!IsNaClAllowed(plugin,
url,
actual_mime_type,
cmd->HasSwitch(switches::kEnableNaCl),
params)) {
return CreatePluginPlaceholder(
render_view, frame, plugin, params, group.get(),
IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED, false, false);
}
}
return render_view->CreatePlugin(frame, plugin, params);
@ -484,6 +445,88 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
}
}
bool ChromeContentRendererClient::IsNaClAllowed(
const webkit::WebPluginInfo& plugin,
const GURL& url,
const std::string& actual_mime_type,
bool enable_nacl,
WebKit::WebPluginParams& params) {
const char* kNaClPluginMimeType = "application/x-nacl";
const char* kNaClPluginManifestAttribute = "nacl";
GURL manifest_url;
if (actual_mime_type == kNaClPluginMimeType) {
manifest_url = url; // Normal embedded NaCl plugin.
} else {
// This is a content type handling NaCl plugin; look for the .nexe URL
// among the MIME type's additonal parameters.
string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute);
for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
if (plugin.mime_types[i].mime_type == actual_mime_type) {
const webkit::WebPluginMimeType& content_type =
plugin.mime_types[i];
for (size_t i = 0;
i < content_type.additional_param_names.size(); ++i) {
if (content_type.additional_param_names[i] == nacl_attr) {
manifest_url = GURL(content_type.additional_param_values[i]);
break;
}
}
break;
}
}
}
// Determine if the manifest URL is part of an extension.
const Extension* extension =
extension_dispatcher_->extensions()->GetByURL(manifest_url);
// Only component, unpacked, and Chrome Web Store extensions are allowed.
bool allowed_extension = extension &&
(extension->from_webstore() ||
extension->location() == Extension::COMPONENT ||
extension->location() == Extension::LOAD);
// Block any other use of NaCl plugin, unless --enable-nacl is set.
if (!allowed_extension && !enable_nacl)
return false;
// Allow dev interfaces for non-extension apps.
bool allow_dev_interfaces = true;
if (allowed_extension) {
// Allow dev interfaces for component and unpacked extensions.
if (extension->location() != Extension::COMPONENT &&
extension->location() != Extension::LOAD) {
// Whitelist all other allowed extensions.
allow_dev_interfaces =
// PDF Viewer plugin
(manifest_url.scheme() == "chrome-extension" &&
manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh");
}
}
WebString dev_attribute = WebString::fromUTF8("@dev");
if (allow_dev_interfaces) {
std::vector<string16> param_names;
std::vector<string16> param_values;
param_names.push_back(dev_attribute);
param_values.push_back(WebString());
AppendParams(
param_names,
param_values,
&params.attributeNames,
&params.attributeValues);
} else {
// If the params somehow contain this special attribute, remove it.
size_t attribute_count = params.attributeNames.size();
for (size_t i = 0; i < attribute_count; ++i) {
if (params.attributeNames[i].equals(dev_attribute))
params.attributeNames[i] = WebString();
}
}
return true;
}
WebPlugin* ChromeContentRendererClient::CreatePluginPlaceholder(
content::RenderView* render_view,
WebFrame* frame,

@ -127,6 +127,14 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
const GURL& new_url,
bool is_initial_navigation);
// Returns true if the NaCl plugin can be created. If it returns true, as a
// side effect, it may add special attributes to params.
bool IsNaClAllowed(const webkit::WebPluginInfo& plugin,
const GURL& url,
const std::string& actual_mime_type,
bool enable_nacl,
WebKit::WebPluginParams& params);
scoped_ptr<ChromeRenderProcessObserver> chrome_observer_;
scoped_ptr<ExtensionDispatcher> extension_dispatcher_;
scoped_ptr<RendererHistogramSnapshots> histogram_snapshots_;

@ -56,26 +56,6 @@ bool enable_3d_interfaces = true;
} // namespace
// By default, disable developer (Dev) interfaces. To enable developer
// interfaces, set the environment variable NACL_ENABLE_PPAPI_DEV to 1.
// Also, the plugin can request whether or not to enable dev interfaces.
bool AreDevInterfacesEnabled() {
static bool first = true;
static bool env_dev_enabled = false;
if (first) {
const char *nacl_enable_ppapi_dev = getenv("NACL_ENABLE_PPAPI_DEV");
if (NULL != nacl_enable_ppapi_dev) {
int v = strtol(nacl_enable_ppapi_dev, (char **) 0, 0);
if (v != 0) {
env_dev_enabled = true;
}
}
first = false;
}
return env_dev_enabled || enable_dev_interfaces;
}
void SetBrowserPppForInstance(PP_Instance instance, BrowserPpp* browser_ppp) {
// If there was no map, create one.
if (instance_to_ppp_map == NULL) {
@ -202,7 +182,7 @@ const void* GetBrowserInterface(const char* interface_name) {
return NULL;
}
// If dev interface is not enabled, reject interfaces containing "(Dev)"
if (!AreDevInterfacesEnabled() && strstr(interface_name, "(Dev)") != NULL) {
if (!enable_dev_interfaces && strstr(interface_name, "(Dev)") != NULL) {
return NULL;
}
if (!enable_3d_interfaces) {

@ -43,7 +43,7 @@ struct NaClSrpcChannel;
namespace ppapi_proxy {
// These functions handle the browser-side (trusted code) mapping of a browser
// Instance to instance-specific data, such as the SRPC communication channel.
// instance to instance-specific data, such as the SRPC communication channel.
// These functions are called by the in-browser (trusted) plugin code, and are
// always called from the main (foreground, UI, ...) thread. As such, they are
// not thread-safe (they do not need to be).
@ -52,11 +52,6 @@ namespace ppapi_proxy {
// channel used to talk to the instance.
class BrowserPpp;
// Returns true if the PPAPI Developer interfaces are enabled.
// To enable, set the environment variable NACL_ENABLE_PPAPI_DEV=1
// Note: Developer interfaces are _not_ enabled by default.
bool AreDevInterfacesEnabled();
// Associate a particular BrowserPpp with a PP_Instance value. This allows the
// browser side to look up information it needs to communicate with the stub.
void SetBrowserPppForInstance(PP_Instance instance,

@ -16,7 +16,6 @@
#include "ppapi/c/pp_completion_callback.h"
#include "srpcgen/ppb_rpc.h"
using ppapi_proxy::AreDevInterfacesEnabled;
using ppapi_proxy::DebugPrintf;
using ppapi_proxy::LookupBrowserPppForInstance;
using ppapi_proxy::MakeRemoteCompletionCallback;
@ -63,8 +62,8 @@ void NaClFileRpcServer::GetFileDesc(
NaClSrpcClosureRunner runner(done);
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
if (AreDevInterfacesEnabled()) {
plugin::Plugin* plugin = LookupBrowserPppForInstance(instance)->plugin();
plugin::Plugin* plugin = LookupBrowserPppForInstance(instance)->plugin();
if (plugin->enable_dev_interfaces()) {
int32_t posix_file_desc = plugin->GetPOSIXFileDesc(url);
DebugPrintf("NaClFile::GetFileDesc: posix_file_desc=%"NACL_PRId32"\n",
posix_file_desc);

@ -103,6 +103,10 @@ const char* const kNaClManifestAttribute = "nacl";
// for the null termination character.
const size_t kNaClManifestMaxFileBytes = 1024 * 1024;
// Define an argument name to enable 'dev' interfaces. To make sure it doesn't
// collide with any user-defined HTML attribute, make the first character '@'.
const char* const kDevAttribute = "@dev";
// URL schemes that we treat in special ways.
const char* const kChromeExtensionUriScheme = "chrome-extension";
const char* const kDataUriScheme = "data";
@ -892,6 +896,11 @@ bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) {
const_cast<char**>(argn),
const_cast<char**>(argv));
if (status) {
// Look for the developer attribute; if it's present, enable 'dev'
// interfaces.
const char* dev_settings = LookupArgument(kDevAttribute);
enable_dev_interfaces_ = (dev_settings != NULL);
const char* type_attr = LookupArgument(kTypeAttribute);
if (type_attr != NULL) {
mime_type_ = nacl::string(type_attr);
@ -904,7 +913,6 @@ bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) {
// and 'nacl' will be the URL for the manifest.
if (IsForeignMIMEType()) {
manifest_url = LookupArgument(kNaClManifestAttribute);
enable_dev_interfaces_ = RequiresDevInterfaces(manifest_url);
}
// Use the document URL as the base for resolving relative URLs to find the
// manifest. This takes into account the setting of <base> tags that
@ -1300,21 +1308,6 @@ void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) {
}
}
// Check manifest_url and return whether or not to enable PPAPI Dev interfaces.
// Returning true here will enable the PPAPI Dev interfaces regardless of
// the environment variable NACL_ENABLE_PPAPI_DEV.
bool Plugin::RequiresDevInterfaces(const nacl::string& manifest_url) {
const char* extensions[] = {
"chrome-extension://acadkphlmlegjaadjagenfimbpphcgnh/", // PDF
};
for (size_t i = 0; i < sizeof(extensions) / sizeof(const char*); ++i) {
if (manifest_url.find(extensions[i]) == 0) {
return true;
}
}
return false;
}
bool Plugin::StartProxiedExecution(NaClSrpcChannel* srpc_channel,
ErrorInfo* error_info) {
PLUGIN_PRINTF(("Plugin::StartProxiedExecution (srpc_channel=%p)\n",

@ -374,9 +374,6 @@ class Plugin : public pp::InstancePrivate {
MethodInfo* GetMethodInfo(uintptr_t method_id, CallType call_type);
// Check url and decide if PPAPI Dev interfaces are required.
bool RequiresDevInterfaces(const nacl::string& manifest_url);
// Callback used when getting the URL for the .nexe file. If the URL loading
// is successful, the file descriptor is opened and can be passed to sel_ldr
// with the sandbox on.

@ -16,31 +16,7 @@
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/dev/ppb_buffer_dev.h"
#include "ppapi/c/dev/ppb_char_set_dev.h"
#include "ppapi/c/dev/ppb_console_dev.h"
#include "ppapi/c/dev/ppb_context_3d_dev.h"
#include "ppapi/c/dev/ppb_context_3d_trusted_dev.h"
#include "ppapi/c/dev/ppb_crypto_dev.h"
#include "ppapi/c/dev/ppb_cursor_control_dev.h"
#include "ppapi/c/dev/ppb_directory_reader_dev.h"
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
#include "ppapi/c/dev/ppb_find_dev.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/c/dev/ppb_fullscreen_dev.h"
#include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
#include "ppapi/c/dev/ppb_layer_compositor_dev.h"
#include "ppapi/c/dev/ppb_memory_dev.h"
#include "ppapi/c/dev/ppb_scrollbar_dev.h"
#include "ppapi/c/dev/ppb_surface_3d_dev.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_transport_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppb_widget_dev.h"
#include "ppapi/c/dev/ppb_zoom_dev.h"
namespace {
@ -49,33 +25,10 @@ namespace {
////////////////////////////////////////////////////////////////////////////////
void TestGetDevInterfaces() {
// This test is run only w/ NACL_ENABLE_PPAPI_DEV=0, which should
// turn off and disable the PPAPI developer interfaces. When they are
// disabled, the interface should return NULL.
CHECK(GetBrowserInterface(PPB_BUFFER_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_CHAR_SET_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_CONSOLE_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_CONTEXT_3D_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_CRYPTO_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_CURSOR_CONTROL_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_DIRECTORYREADER_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_FILECHOOSER_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_FIND_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_FONT_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_FULLSCREEN_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(
PPB_GLES_CHROMIUM_TEXTURE_MAPPING_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_LAYER_COMPOSITOR_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_MEMORY_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_SCROLLBAR_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_SURFACE_3D_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_TESTING_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_TRANSPORT_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_URLUTIL_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_VAR_DEPRECATED_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_VIDEODECODER_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_WIDGET_DEV_INTERFACE) == NULL);
CHECK(GetBrowserInterface(PPB_ZOOM_DEV_INTERFACE) == NULL);
// This test is run as a simple embedded .nexe with --enable-nacl. It should
// have access to all dev interfaces. Only test one to make the test more
// robust as interfaces change.
EXPECT(GetBrowserInterface(PPB_CURSOR_CONTROL_DEV_INTERFACE) != NULL);
TEST_PASSED;
}

@ -31,9 +31,7 @@ function setupTests(tester, plugin) {
</head>
<body>
<h1>PPAPI Dev Interface Test</h1>
NOTE: requires --enable-pepper-testing. Also, this test should be run with
PPAPI Dev interfaces disabled; the environment variable NACL_ENABLE_PPAPI_DEV
should be set to 0 or unset.
NOTE: requires --enable-pepper-testing.
<br><br>
<table>
<tr>