Commit aec5ed53 authored by hamaji@chromium.org's avatar hamaji@chromium.org

Pepper: Whitelist dev channel APIs for some apps.

Some applications need access to dev channel APIs before they will
become stable. As written, this change only performs whitelisting for NaCl
apps; I don't think we have any need for enabling this in the non-NaCl case.

I need to find a good way to test this.

BUG=383937
R=dmichael@chromium.org, jln@chromium.org, piman@chromium.org

Review URL: https://codereview.chromium.org/338523007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278645 0039d316-1c4b-4281-b951-d872f2087c98
parent 2c1cb79c
......@@ -280,6 +280,14 @@ namespace {
base::LazyInstance<std::string> g_io_thread_application_locale;
#if defined(ENABLE_PLUGINS)
// TODO(teravest): Add renderer-side API-specific checking for these APIs so
// that blanket permission isn't granted to all dev channel APIs for these.
// http://crbug.com/386743
const char* const kPredefinedAllowedDevChannelOrigins[] = {
"6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/383937
"4EB74897CB187C7633357C2FE832E0AD6A44883A" // see crbug.com/383937
};
const char* const kPredefinedAllowedFileHandleOrigins[] = {
"6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/234789
"4EB74897CB187C7633357C2FE832E0AD6A44883A" // see crbug.com/234789
......@@ -642,6 +650,8 @@ namespace chrome {
ChromeContentBrowserClient::ChromeContentBrowserClient()
: prerender_tracker_(NULL) {
#if defined(ENABLE_PLUGINS)
for (size_t i = 0; i < arraysize(kPredefinedAllowedDevChannelOrigins); ++i)
allowed_dev_channel_origins_.insert(kPredefinedAllowedDevChannelOrigins[i]);
for (size_t i = 0; i < arraysize(kPredefinedAllowedFileHandleOrigins); ++i)
allowed_file_handle_origins_.insert(kPredefinedAllowedFileHandleOrigins[i]);
for (size_t i = 0; i < arraysize(kPredefinedAllowedSocketOrigins); ++i)
......@@ -2808,8 +2818,6 @@ bool ChromeContentBrowserClient::IsPluginAllowedToCallRequestOSFileHandle(
extension_set = extensions::ExtensionSystem::Get(profile)->
extension_service()->extensions();
}
// TODO(teravest): Populate allowed_file_handle_origins_ when FileIO is moved
// from the renderer to the browser.
return IsExtensionOrSharedModuleWhitelisted(url, extension_set,
allowed_file_handle_origins_) ||
IsHostAllowedByCommandLine(url, extension_set,
......@@ -2819,7 +2827,9 @@ bool ChromeContentBrowserClient::IsPluginAllowedToCallRequestOSFileHandle(
#endif
}
bool ChromeContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs() {
bool ChromeContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs(
content::BrowserContext* browser_context,
const GURL& url) {
#if defined(ENABLE_PLUGINS)
// Allow access for tests.
if (CommandLine::ForCurrentProcess()->HasSwitch(
......@@ -2827,6 +2837,20 @@ bool ChromeContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs() {
return true;
}
Profile* profile = Profile::FromBrowserContext(browser_context);
const extensions::ExtensionSet* extension_set = NULL;
if (profile) {
extension_set = extensions::ExtensionSystem::Get(profile)->
extension_service()->extensions();
}
// Allow access for whitelisted applications.
if (IsExtensionOrSharedModuleWhitelisted(url,
extension_set,
allowed_dev_channel_origins_)) {
return true;
}
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
// Allow dev channel APIs to be used on "Canary", "Dev", and "Unknown"
// releases of Chrome. Permitting "Unknown" allows these APIs to be used on
......
......@@ -286,7 +286,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
virtual bool IsPluginAllowedToCallRequestOSFileHandle(
content::BrowserContext* browser_context,
const GURL& url) OVERRIDE;
virtual bool IsPluginAllowedToUseDevChannelAPIs() OVERRIDE;
virtual bool IsPluginAllowedToUseDevChannelAPIs(
content::BrowserContext* browser_context,
const GURL& url) OVERRIDE;
virtual net::CookieStore* OverrideCookieStoreForRenderProcess(
int render_process_id) OVERRIDE;
......@@ -316,6 +318,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
std::set<std::string> allowed_socket_origins_;
// Set of origins that can get a handle for FileIO from NaCl.
std::set<std::string> allowed_file_handle_origins_;
// Set of origins that can use "dev chanel" APIs from NaCl, even on stable
// versions of Chrome.
std::set<std::string> allowed_dev_channel_origins_;
#endif
scoped_ptr<extensions::BrowserPermissionsPolicyDelegate>
permissions_policy_delegate_;
......
......@@ -10,13 +10,56 @@
#include "components/nacl/browser/nacl_process_host.h"
#include "components/nacl/browser/pnacl_host.h"
#include "components/nacl/common/nacl_host_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_platform_file.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "url/gurl.h"
namespace nacl {
namespace {
ppapi::PpapiPermissions GetNaClPermissions(
uint32 permission_bits,
content::BrowserContext* browser_context,
const GURL& document_url) {
// Only allow NaCl plugins to request certain permissions. We don't want
// a compromised renderer to be able to start a nacl plugin with e.g. Flash
// permissions which may expand the surface area of the sandbox.
uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV;
if (content::PluginService::GetInstance()->PpapiDevChannelSupported(
browser_context, document_url))
masked_bits |= ppapi::PERMISSION_DEV_CHANNEL;
return ppapi::PpapiPermissions::GetForCommandLine(masked_bits);
}
ppapi::PpapiPermissions GetPpapiPermissions(uint32 permission_bits,
int render_process_id,
int render_view_id) {
// We get the URL from WebContents from the RenderViewHost, since we don't
// have a BrowserPpapiHost yet.
content::RenderProcessHost* host =
content::RenderProcessHost::FromID(render_process_id);
content::RenderViewHost* view_host =
content::RenderViewHost::FromID(render_process_id, render_view_id);
GURL document_url;
content::WebContents* contents =
content::WebContents::FromRenderViewHost(view_host);
if (contents)
document_url = contents->GetLastCommittedURL();
return GetNaClPermissions(permission_bits,
host->GetBrowserContext(),
document_url);
}
} // namespace
NaClHostMessageFilter::NaClHostMessageFilter(
int render_process_id,
bool is_off_the_record,
......@@ -72,8 +115,35 @@ net::HostResolver* NaClHostMessageFilter::GetHostResolver() {
void NaClHostMessageFilter::OnLaunchNaCl(
const nacl::NaClLaunchParams& launch_params,
IPC::Message* reply_msg) {
// PNaCl hack
if (!launch_params.enable_dyncode_syscalls) {
uint32 perms = launch_params.permission_bits & ppapi::PERMISSION_DEV;
LaunchNaClContinuation(
launch_params,
reply_msg,
ppapi::PpapiPermissions(perms));
return;
}
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&GetPpapiPermissions,
launch_params.permission_bits,
render_process_id_,
launch_params.render_view_id),
base::Bind(&NaClHostMessageFilter::LaunchNaClContinuation,
this,
launch_params,
reply_msg));
}
void NaClHostMessageFilter::LaunchNaClContinuation(
const nacl::NaClLaunchParams& launch_params,
IPC::Message* reply_msg,
ppapi::PpapiPermissions permissions) {
NaClProcessHost* host = new NaClProcessHost(
GURL(launch_params.manifest_url),
permissions,
launch_params.render_view_id,
launch_params.permission_bits,
launch_params.uses_irt,
......
......@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_message_filter.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
class GURL;
......@@ -50,6 +51,9 @@ class NaClHostMessageFilter : public content::BrowserMessageFilter {
void OnLaunchNaCl(const NaClLaunchParams& launch_params,
IPC::Message* reply_msg);
void LaunchNaClContinuation(const nacl::NaClLaunchParams& launch_params,
IPC::Message* reply_msg,
ppapi::PpapiPermissions permissions);
void OnGetReadonlyPnaclFd(const std::string& filename,
IPC::Message* reply_msg);
void OnNaClCreateTemporaryFile(IPC::Message* reply_msg);
......
......@@ -38,6 +38,8 @@
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
......@@ -228,16 +230,6 @@ bool ShareHandleToSelLdr(
return true;
}
ppapi::PpapiPermissions GetNaClPermissions(uint32 permission_bits) {
// Only allow NaCl plugins to request certain permissions. We don't want
// a compromised renderer to be able to start a nacl plugin with e.g. Flash
// permissions which may expand the surface area of the sandbox.
uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV;
if (content::PluginService::GetInstance()->PpapiDevChannelSupported())
masked_bits |= ppapi::PERMISSION_DEV_CHANNEL;
return ppapi::PpapiPermissions::GetForCommandLine(masked_bits);
}
} // namespace
namespace nacl {
......@@ -257,6 +249,7 @@ unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ =
ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds;
NaClProcessHost::NaClProcessHost(const GURL& manifest_url,
ppapi::PpapiPermissions permissions,
int render_view_id,
uint32 permission_bits,
bool uses_irt,
......@@ -267,7 +260,7 @@ NaClProcessHost::NaClProcessHost(const GURL& manifest_url,
bool off_the_record,
const base::FilePath& profile_directory)
: manifest_url_(manifest_url),
permissions_(GetNaClPermissions(permission_bits)),
permissions_(permissions),
#if defined(OS_WIN)
process_launched_by_broker_(false),
#endif
......
......@@ -45,6 +45,7 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate {
public:
// manifest_url: the URL of the manifest of the Native Client plugin being
// executed.
// permissions: PPAPI permissions, to control access to private APIs.
// render_view_id: RenderView routing id, to control access to private APIs.
// permission_bits: controls which interfaces the NaCl plugin can use.
// uses_irt: whether the launched process should use the IRT.
......@@ -60,6 +61,7 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate {
// off_the_record: was the process launched from an incognito renderer?
// profile_directory: is the path of current profile directory.
NaClProcessHost(const GURL& manifest_url,
ppapi::PpapiPermissions permissions,
int render_view_id,
uint32 permission_bits,
bool uses_irt,
......
......@@ -51,6 +51,7 @@ NaClLaunchParams::NaClLaunchParams(const NaClLaunchParams& l) {
render_view_id = l.render_view_id;
permission_bits = l.permission_bits;
uses_irt = l.uses_irt;
uses_nonsfi_mode = l.uses_nonsfi_mode;
enable_dyncode_syscalls = l.enable_dyncode_syscalls;
enable_exception_handling = l.enable_exception_handling;
enable_crash_throttling = l.enable_crash_throttling;
......
......@@ -852,9 +852,11 @@ bool PluginServiceImpl::IsPluginWindow(HWND window) {
}
#endif
bool PluginServiceImpl::PpapiDevChannelSupported() {
bool PluginServiceImpl::PpapiDevChannelSupported(
BrowserContext* browser_context,
const GURL& document_url) {
return content::GetContentClient()->browser()->
IsPluginAllowedToUseDevChannelAPIs();
IsPluginAllowedToUseDevChannelAPIs(browser_context, document_url);
}
} // namespace content
......@@ -115,7 +115,8 @@ class CONTENT_EXPORT PluginServiceImpl
// Returns true iff the given HWND is a plugin.
bool IsPluginWindow(HWND window);
#endif
virtual bool PpapiDevChannelSupported() OVERRIDE;
virtual bool PpapiDevChannelSupported(BrowserContext* browser_context,
const GURL& document_url) OVERRIDE;
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. This will start a process to host the
......
......@@ -232,7 +232,11 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
: profile_data_directory_(profile_data_directory),
is_broker_(false) {
uint32 base_permissions = info.permissions;
if (GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs())
// We don't have to do any whitelisting for APIs in this process host, so
// don't bother passing a browser context or document url here.
if (GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs(
NULL, GURL()))
base_permissions |= ppapi::PERMISSION_DEV_CHANNEL;
permissions_ = ppapi::PpapiPermissions::GetForCommandLine(base_permissions);
......
......@@ -324,7 +324,9 @@ bool ContentBrowserClient::IsPluginAllowedToCallRequestOSFileHandle(
return false;
}
bool ContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs() {
bool ContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs(
BrowserContext* browser_context,
const GURL& url) {
return false;
}
......
......@@ -641,7 +641,9 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& url);
// Returns true if dev channel APIs are available for plugins.
virtual bool IsPluginAllowedToUseDevChannelAPIs();
virtual bool IsPluginAllowedToUseDevChannelAPIs(
BrowserContext* browser_context,
const GURL& url);
// Returns a special cookie store to use for a given render process, or NULL
// if the default cookie store should be used
......
......@@ -161,7 +161,8 @@ class PluginService {
#endif
// Returns true iff PPAPI "dev channel" methods are supported.
virtual bool PpapiDevChannelSupported() = 0;
virtual bool PpapiDevChannelSupported(BrowserContext* browser_context,
const GURL& document_url) = 0;
};
} // namespace content
......
# New interfaces that use dev channel permissions should have a security review
# until http://crbug.com/386743 is resolved.
per-file interfaces_ppb_public_dev_channel.h=set noparent
per-file interfaces_ppb_public_dev_channel.h=cevans@chromium.org
per-file interfaces_ppb_public_dev_channel.h=dcheng@chromium.org
per-file interfaces_ppb_public_dev_channel.h=inferno@chromium.org
per-file interfaces_ppb_public_dev_channel.h=jln@chromium.org
per-file interfaces_ppb_public_dev_channel.h=jschuh@chromium.org
per-file interfaces_ppb_public_dev_channel.h=kenrb@chromium.org
per-file interfaces_ppb_public_dev_channel.h=nasko@chromium.org
per-file interfaces_ppb_public_dev_channel.h=palmer@chromium.org
per-file interfaces_ppb_public_dev_channel.h=tsepez@chromium.org
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment