0

Hook up PpapiPermissions in more places.

This doesn't actually do much more checking of the permissions, but it should wire it up everywhere we'll need it. It will also at least only return public interfaces via GetInterface in the proxy now unless other bits are supplied.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159729 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
brettw@chromium.org
2012-10-02 18:12:41 +00:00
parent 8a56410423
commit 195d4cde0d
42 changed files with 324 additions and 86 deletions

@ -0,0 +1,3 @@
include_rules = [
"+ppapi/shared_impl",
]

@ -131,8 +131,10 @@ bool NaClProcessHost::PluginListener::OnMessageReceived(
return host_->OnUntrustedMessageForwarded(msg);
}
// TODO(brettw) bug 153036 set the pepper permissions up for dev interfaces.
NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record)
: manifest_url_(manifest_url),
permissions_(ppapi::PpapiPermissions::GetForCommandLine(0)),
#if defined(OS_WIN)
process_launched_by_broker_(false),
#elif defined(OS_LINUX)
@ -758,6 +760,7 @@ void NaClProcessHost::OnPpapiChannelCreated(
ipc_proxy_channel_->Send(
new PpapiMsg_CreateNaClChannel(
chrome_render_message_filter_->render_process_id(),
permissions_,
chrome_render_message_filter_->off_the_record(),
SerializedHandle(SerializedHandle::CHANNEL_HANDLE,
IPC::InvalidPlatformFileForTransit())));

@ -18,6 +18,7 @@
#include "googleurl/src/gurl.h"
#include "ipc/ipc_channel_handle.h"
#include "net/base/tcp_listen_socket.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
class ChromeRenderMessageFilter;
class CommandLine;
@ -144,6 +145,7 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate {
bool OnUntrustedMessageForwarded(const IPC::Message& msg);
GURL manifest_url_;
ppapi::PpapiPermissions permissions_;
#if defined(OS_WIN)
// This field becomes true when the broker successfully launched

@ -62,6 +62,7 @@
'../media/media.gyp:media_test_support',
'../net/net.gyp:net',
'../net/net.gyp:net_test_support',
'../ppapi/ppapi_internal.gyp:ppapi_shared',
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',

@ -34,6 +34,7 @@ bool IsPepperFlashEnabledByDefault() {
int32 kPepperFlashPermissions = ppapi::PERMISSION_DEV |
ppapi::PERMISSION_PRIVATE |
ppapi::PERMISSION_BYPASS_USER_GESTURE;
ppapi::PERMISSION_BYPASS_USER_GESTURE |
ppapi::PERMISSION_FLASH;

@ -161,10 +161,11 @@ class OutOfProcessProxy : public PluginDelegate::OutOfProcessProxy {
PP_Module pp_module,
PP_GetInterface_Func local_get_interface,
const ppapi::Preferences& preferences,
SyncMessageStatusReceiver* status_receiver) {
SyncMessageStatusReceiver* status_receiver,
const ppapi::PpapiPermissions& permissions) {
dispatcher_delegate_.reset(new ProxyChannelDelegate);
dispatcher_.reset(new ppapi::proxy::HostDispatcher(
pp_module, local_get_interface, status_receiver));
pp_module, local_get_interface, status_receiver, permissions));
if (!dispatcher_->InitHostWithChannel(dispatcher_delegate_.get(),
channel_handle,
@ -229,12 +230,17 @@ PP_Bool StartPpapiProxy(PP_Instance instance) {
scoped_refptr<PluginModule> nacl_plugin_module(
plugin_module->CreateModuleForNaClInstance());
// TODO(brettw) bug 153036 set NaCl permissions to allow dev interface
// usage when necessary.
ppapi::PpapiPermissions permissions;
if (out_of_process_proxy->Init(
channel_handle,
nacl_plugin_module->pp_module(),
PluginModule::GetLocalGetInterfaceFunc(),
ppapi::Preferences(render_view->GetWebkitPreferences()),
status_receiver.get())) {
status_receiver.get(),
permissions)) {
nacl_plugin_module->InitAsProxiedNaCl(
out_of_process_proxy.PassAs<PluginDelegate::OutOfProcessProxy>(),
instance);

3
chrome/test/ppapi/DEPS Normal file

@ -0,0 +1,3 @@
include_rules = [
"+ppapi/shared_impl",
]

@ -36,6 +36,7 @@
#include "media/audio/audio_manager.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/gl/gl_switches.h"
#include "webkit/plugins/plugin_switches.h"

@ -161,7 +161,9 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
const content::PepperPluginInfo& info,
const FilePath& profile_data_directory,
net::HostResolver* host_resolver)
: network_observer_(new PluginNetworkObserver(this)),
: permissions_(
ppapi::PpapiPermissions::GetForCommandLine(info.permissions)),
network_observer_(new PluginNetworkObserver(this)),
profile_data_directory_(profile_data_directory),
is_broker_(false) {
process_.reset(new BrowserChildProcessHostImpl(
@ -170,8 +172,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
filter_ = new PepperMessageFilter(PepperMessageFilter::PLUGIN,
host_resolver);
ppapi::PpapiPermissions permissions(info.permissions);
host_impl_ = new content::BrowserPpapiHostImpl(this, permissions);
host_impl_ = new content::BrowserPpapiHostImpl(this, permissions_);
file_filter_ = new PepperTrustedFileMessageFilter(
process_->GetData().id, info.name, profile_data_directory);
@ -315,7 +316,7 @@ void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
// This will actually load the plugin. Errors will actually not be reported
// back at this point. Instead, the plugin will fail to establish the
// connections when we request them on behalf of the renderer(s).
Send(new PpapiMsg_LoadPlugin(plugin_path_));
Send(new PpapiMsg_LoadPlugin(plugin_path_, permissions_));
// Process all pending channel requests from the renderers.
for (size_t i = 0; i < pending_requests_.size(); i++)

@ -18,6 +18,7 @@
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "ipc/ipc_sender.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
class BrowserChildProcessHostImpl;
@ -138,6 +139,7 @@ class PpapiPluginProcessHost : public content::BrowserChildProcessHostDelegate,
// Handles most requests from the plugin. May be NULL.
scoped_refptr<PepperMessageFilter> filter_;
ppapi::PpapiPermissions permissions_;
scoped_refptr<content::BrowserPpapiHostImpl> host_impl_;
// Handles filesystem requests from flash plugins. May be NULL.

@ -114,6 +114,7 @@
#include "ipc/ipc_sync_channel.h"
#include "media/base/media_switches.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_switches.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"

@ -71,9 +71,7 @@ void ComputePluginsFromCommandLine(
}
// Command-line plugins get full permissions.
plugin.permissions = ppapi::PERMISSION_DEV |
ppapi::PERMISSION_PRIVATE |
ppapi::PERMISSION_BYPASS_USER_GESTURE;
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
plugins->push_back(plugin);
}

@ -17,8 +17,10 @@ const int kPluginReleaseTimeSeconds = 30;
PluginProcessDispatcher::PluginProcessDispatcher(
PP_GetInterface_Func get_interface,
const ppapi::PpapiPermissions& permissions,
bool incognito)
: ppapi::proxy::PluginDispatcher(get_interface,
permissions,
incognito) {
ChildProcess::current()->AddRefProcess();
}

@ -14,6 +14,7 @@
class PluginProcessDispatcher : public ppapi::proxy::PluginDispatcher {
public:
PluginProcessDispatcher(PP_GetInterface_Func get_interface,
const ppapi::PpapiPermissions& permissions,
bool incognito);
virtual ~PluginProcessDispatcher();

@ -211,9 +211,14 @@ void PpapiThread::Unregister(uint32 plugin_dispatcher_id) {
plugin_dispatchers_.erase(plugin_dispatcher_id);
}
void PpapiThread::OnMsgLoadPlugin(const FilePath& path) {
void PpapiThread::OnMsgLoadPlugin(const FilePath& path,
const ppapi::PpapiPermissions& permissions) {
SavePluginName(path);
// This must be set before calling into the plugin so it can get the
// interfaces it has permission for.
ppapi::proxy::InterfaceList::SetProcessGlobalPermissions(permissions);
std::string error;
base::ScopedNativeLibrary library(base::LoadNativeLibrary(path, &error));
@ -294,10 +299,11 @@ void PpapiThread::OnMsgLoadPlugin(const FilePath& path) {
}
library_.Reset(library.Release());
permissions_ = permissions;
}
void PpapiThread::OnMsgCreateChannel(int renderer_id,
bool incognito) {
void PpapiThread::OnMsgCreateChannel(int renderer_id, bool incognito) {
IPC::ChannelHandle channel_handle;
if (!library_.is_valid() || // Plugin couldn't be loaded.
!SetupRendererChannel(renderer_id, incognito, &channel_handle)) {
@ -358,7 +364,9 @@ bool PpapiThread::SetupRendererChannel(int renderer_id,
dispatcher = broker_dispatcher;
} else {
PluginProcessDispatcher* plugin_dispatcher =
new PluginProcessDispatcher(get_plugin_interface_, incognito);
new PluginProcessDispatcher(get_plugin_interface_,
permissions_,
incognito);
init_result = plugin_dispatcher->InitPluginWithChannel(this,
plugin_handle,
false);

@ -67,7 +67,8 @@ class PpapiThread : public ChildThread,
virtual void SetActiveURL(const std::string& url) OVERRIDE;
// Message handlers.
void OnMsgLoadPlugin(const FilePath& path);
void OnMsgLoadPlugin(const FilePath& path,
const ppapi::PpapiPermissions& permissions);
void OnMsgCreateChannel(int renderer_id,
bool incognito);
void OnMsgResourceReply(
@ -90,6 +91,8 @@ class PpapiThread : public ChildThread,
base::ScopedNativeLibrary library_;
ppapi::PpapiPermissions permissions_;
// Global state tracking for the proxy.
ppapi::proxy::PluginGlobals plugin_globals_;

@ -28,7 +28,7 @@ namespace old {
GuestToEmbedderChannel::GuestToEmbedderChannel(
const std::string& embedder_channel_name,
const IPC::ChannelHandle& embedder_channel_handle)
: Dispatcher(NULL),
: Dispatcher(NULL, ppapi::PpapiPermissions()),
embedder_channel_name_(embedder_channel_name),
embedder_channel_handle_(embedder_channel_handle) {
SetSerializationRules(new BrowserPluginVarSerializationRules());

@ -133,7 +133,7 @@ class HostDispatcherWrapper
dispatcher_delegate_.reset(new PepperProxyChannelDelegateImpl);
dispatcher_.reset(new ppapi::proxy::HostDispatcher(
module_->pp_module(), local_get_interface, filter));
module_->pp_module(), local_get_interface, filter, permissions_));
if (!dispatcher_->InitHostWithChannel(dispatcher_delegate_.get(),
channel_handle,
@ -369,7 +369,9 @@ PepperPluginDelegateImpl::CreatePepperPluginModule(
// In-process plugin not preloaded, it probably couldn't be initialized.
return scoped_refptr<webkit::ppapi::PluginModule>();
}
ppapi::PpapiPermissions permissions(info->permissions);
ppapi::PpapiPermissions permissions =
ppapi::PpapiPermissions::GetForCommandLine(info->permissions);
// Out of process: have the browser start the plugin process for us.
IPC::ChannelHandle channel_handle;

@ -40,6 +40,8 @@
'shared_impl/ppapi_permissions.h',
'shared_impl/ppapi_preferences.cc',
'shared_impl/ppapi_preferences.h',
'shared_impl/ppapi_switches.cc',
'shared_impl/ppapi_switches.h',
'shared_impl/ppb_audio_config_shared.cc',
'shared_impl/ppb_audio_config_shared.h',
'shared_impl/ppb_audio_input_shared.cc',

@ -17,9 +17,10 @@
namespace ppapi {
namespace proxy {
Dispatcher::Dispatcher(PP_GetInterface_Func local_get_interface)
: disallow_trusted_interfaces_(false), // TODO(brettw) make this settable.
local_get_interface_(local_get_interface) {
Dispatcher::Dispatcher(PP_GetInterface_Func local_get_interface,
const PpapiPermissions& permissions)
: local_get_interface_(local_get_interface),
permissions_(permissions) {
}
Dispatcher::~Dispatcher() {

@ -83,8 +83,11 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel {
return local_get_interface_;
}
const PpapiPermissions& permissions() const { return permissions_; }
protected:
explicit Dispatcher(PP_GetInterface_Func local_get_interface);
explicit Dispatcher(PP_GetInterface_Func local_get_interface,
const PpapiPermissions& permissions);
// Setter for the derived classes to set the appropriate var serialization.
// Takes one reference of the given pointer, which must be on the heap.
@ -94,10 +97,6 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel {
// default implementation does nothing, derived classes can override.
virtual void OnInvalidMessageReceived();
bool disallow_trusted_interfaces() const {
return disallow_trusted_interfaces_;
}
protected:
std::vector<IPC::Listener*> filters_;
@ -114,6 +113,8 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel {
scoped_refptr<VarSerializationRules> serialization_rules_;
PpapiPermissions permissions_;
DISALLOW_COPY_AND_ASSIGN(Dispatcher);
};

@ -61,8 +61,9 @@ class BoolRestorer {
HostDispatcher::HostDispatcher(PP_Module module,
PP_GetInterface_Func local_get_interface,
SyncMessageStatusReceiver* sync_status)
: Dispatcher(local_get_interface),
SyncMessageStatusReceiver* sync_status,
const PpapiPermissions& permissions)
: Dispatcher(local_get_interface, permissions),
sync_status_(sync_status),
pp_module_(module),
ppb_proxy_(NULL),

@ -50,7 +50,8 @@ class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher {
// You must call InitHostWithChannel after the constructor.
HostDispatcher(PP_Module module,
PP_GetInterface_Func local_get_interface,
SyncMessageStatusReceiver* sync_status);
SyncMessageStatusReceiver* sync_status,
const PpapiPermissions& permissions);
~HostDispatcher();
// You must call this function before anything else. Returns true on success.

@ -4,6 +4,7 @@
#include "ppapi/proxy/interface_list.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "ppapi/c/dev/ppb_audio_input_dev.h"
#include "ppapi/c/dev/ppb_buffer_dev.h"
@ -157,6 +158,8 @@ InterfaceProxy* ProxyFactory(Dispatcher* dispatcher) {
return new ProxyClass(dispatcher);
}
base::LazyInstance<PpapiPermissions> g_process_global_permissions;
} // namespace
InterfaceList::InterfaceList() {
@ -168,19 +171,34 @@ InterfaceList::InterfaceList() {
AddProxy(PROXY_API_ID(api_name), &PROXY_FACTORY_NAME(api_name));
// Register each proxied interface by calling AddPPB for each supported
// interface.
// interface. Set current_required_permission to the appropriate value for
// the value you want expanded by this macro.
#define PROXIED_IFACE(api_name, iface_str, iface_struct) \
AddPPB(iface_str, PROXY_API_ID(api_name), \
INTERFACE_THUNK_NAME(iface_struct)());
INTERFACE_THUNK_NAME(iface_struct)(), \
current_required_permission);
{
Permission current_required_permission = PERMISSION_NONE;
#include "ppapi/thunk/interfaces_ppb_public_stable.h"
}
#include "ppapi/thunk/interfaces_ppb_public_stable.h"
#if !defined(OS_NACL)
#include "ppapi/thunk/interfaces_ppb_public_dev.h"
#include "ppapi/thunk/interfaces_ppb_private.h"
{
Permission current_required_permission = PERMISSION_DEV;
#include "ppapi/thunk/interfaces_ppb_public_dev.h"
}
{
Permission current_required_permission = PERMISSION_PRIVATE;
#include "ppapi/thunk/interfaces_ppb_private.h"
}
#endif
#if !defined(OS_NACL)
#include "ppapi/thunk/interfaces_ppb_private_flash.h"
{
Permission current_required_permission = PERMISSION_FLASH;
#include "ppapi/thunk/interfaces_ppb_private_flash.h"
}
#endif
#undef PROXIED_API
@ -193,44 +211,48 @@ InterfaceList::InterfaceList() {
AddProxy(API_ID_RESOURCE_CREATION, &ResourceCreationProxy::Create);
AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create);
AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE,
PPB_Core_Proxy::GetPPB_Core_Interface());
PPB_Core_Proxy::GetPPB_Core_Interface(), PERMISSION_NONE);
AddPPB(PPB_MESSAGELOOP_DEV_INTERFACE_0_1, API_ID_NONE,
PPB_MessageLoop_Proxy::GetInterface());
PPB_MessageLoop_Proxy::GetInterface(), PERMISSION_DEV);
AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetInterface());
PPB_OpenGLES2_Shared::GetInterface(), PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetInstancedArraysInterface());
PPB_OpenGLES2_Shared::GetInstancedArraysInterface(), PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetFramebufferBlitInterface());
PPB_OpenGLES2_Shared::GetFramebufferBlitInterface(), PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface());
PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface(),
PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface());
PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface(),
PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetChromiumMapSubInterface());
PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetChromiumMapSubInterface());
PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE);
AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetQueryInterface());
PPB_OpenGLES2_Shared::GetQueryInterface(), PERMISSION_NONE);
#if !defined(OS_NACL)
AddPPB(PPB_FLASH_PRINT_INTERFACE_1_0, API_ID_PPB_FLASH,
PPB_Flash_Proxy::GetFlashPrintInterface());
PPB_Flash_Proxy::GetFlashPrintInterface(),
PERMISSION_FLASH);
#endif
AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, API_ID_NONE,
PPB_Var_Shared::GetVarArrayBufferInterface1_0());
PPB_Var_Shared::GetVarArrayBufferInterface1_0(),
PERMISSION_DEV);
AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE,
PPB_Var_Shared::GetVarInterface1_1());
PPB_Var_Shared::GetVarInterface1_1(), PERMISSION_NONE);
AddPPB(PPB_VAR_INTERFACE_1_0, API_ID_NONE,
PPB_Var_Shared::GetVarInterface1_0());
PPB_Var_Shared::GetVarInterface1_0(), PERMISSION_NONE);
#if !defined(OS_NACL)
// PPB (browser) interfaces.
// Do not add more stuff here, they should be added to interface_list*.h
// TODO(brettw) remove these.
AddPPB(PPB_Instance_Proxy::GetInfoPrivate());
AddPPB(PPB_PDF_Proxy::GetInfo());
AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo());
AddPPB(PPB_Var_Deprecated_Proxy::GetInfo());
AddPPB(PPB_Instance_Proxy::GetInfoPrivate(), PERMISSION_PRIVATE);
AddPPB(PPB_PDF_Proxy::GetInfo(), PERMISSION_PRIVATE);
AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo(), PERMISSION_PRIVATE);
AddPPB(PPB_Var_Deprecated_Proxy::GetInfo(), PERMISSION_DEV);
// TODO(tomfinegan): Figure out where to put these once we refactor things
// to load the PPP interface struct from the PPB interface.
@ -240,7 +262,7 @@ InterfaceList::InterfaceList() {
API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
PPP_ContentDecryptor_Private_Proxy::GetProxyInterface());
#endif
AddPPB(PPB_Testing_Proxy::GetInfo());
AddPPB(PPB_Testing_Proxy::GetInfo(), PERMISSION_TESTING);
// PPP (plugin) interfaces.
// TODO(brettw) move these to interface_list*.h
@ -276,6 +298,12 @@ InterfaceList* InterfaceList::GetInstance() {
return Singleton<InterfaceList>::get();
}
// static
void InterfaceList::SetProcessGlobalPermissions(
const PpapiPermissions& permissions) {
g_process_global_permissions.Get() = permissions;
}
ApiID InterfaceList::GetIDForPPBInterface(const std::string& name) const {
NameToInterfaceInfoMap::const_iterator found =
name_to_browser_info_.find(name);
@ -305,7 +333,11 @@ const void* InterfaceList::GetInterfaceForPPB(const std::string& name) const {
name_to_browser_info_.find(name);
if (found == name_to_browser_info_.end())
return NULL;
return found->second.iface;
if (g_process_global_permissions.Get().HasPermission(
found->second.required_permission))
return found->second.iface;
return NULL;
}
const void* InterfaceList::GetInterfaceForPPP(const std::string& name) const {
@ -334,21 +366,22 @@ void InterfaceList::AddProxy(ApiID id,
void InterfaceList::AddPPB(const char* name,
ApiID id,
const void* iface) {
const void* iface,
Permission perm) {
DCHECK(name_to_browser_info_.find(name) == name_to_browser_info_.end());
name_to_browser_info_[name] = InterfaceInfo(id, iface);
name_to_browser_info_[name] = InterfaceInfo(id, iface, perm);
}
void InterfaceList::AddPPP(const char* name,
ApiID id,
const void* iface) {
DCHECK(name_to_plugin_info_.find(name) == name_to_plugin_info_.end());
name_to_plugin_info_[name] = InterfaceInfo(id, iface);
name_to_plugin_info_[name] = InterfaceInfo(id, iface, PERMISSION_NONE);
}
void InterfaceList::AddPPB(const InterfaceProxy::Info* info) {
void InterfaceList::AddPPB(const InterfaceProxy::Info* info, Permission perm) {
AddProxy(info->id, info->create_proxy);
AddPPB(info->name, info->id, info->interface_ptr);
AddPPB(info->name, info->id, info->interface_ptr, perm);
}
void InterfaceList::AddPPP(const InterfaceProxy::Info* info) {

@ -10,6 +10,8 @@
#include "base/basictypes.h"
#include "ppapi/proxy/interface_proxy.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
namespace ppapi {
namespace proxy {
@ -21,6 +23,19 @@ class InterfaceList {
static InterfaceList* GetInstance();
// Sets the permissions that the interface list will use to compute
// whether an interface is available to the current process. By default,
// this will be "no permissions", which will give only access to public
// stable interfaces via GetInterface.
//
// IMPORTANT: This is not a security boundary. Malicious plugins can bypass
// this check since they run in the same address space as this code in the
// plugin process. A real security check is required for all IPC messages.
// This check just allows us to return NULL for interfaces you "shouldn't" be
// using to keep honest plugins honest.
static PPAPI_PROXY_EXPORT void SetProcessGlobalPermissions(
const PpapiPermissions& permissions);
// Looks up the ID for the given interface name. Returns API_ID_NONE if
// the interface string is not found.
ApiID GetIDForPPBInterface(const std::string& name) const;
@ -39,29 +54,42 @@ class InterfaceList {
struct InterfaceInfo {
InterfaceInfo()
: id(API_ID_NONE),
iface(NULL) {
iface(NULL),
required_permission(PERMISSION_NONE) {
}
InterfaceInfo(ApiID in_id, const void* in_interface)
InterfaceInfo(ApiID in_id, const void* in_interface, Permission in_perm)
: id(in_id),
iface(in_interface) {
iface(in_interface),
required_permission(in_perm) {
}
ApiID id;
const void* iface;
// Permission required to return non-null for this interface. This will
// be checked with the value set via SetProcessGlobalPermissionBits when
// an interface is requested.
Permission required_permission;
};
typedef std::map<std::string, InterfaceInfo> NameToInterfaceInfoMap;
void AddProxy(ApiID id, InterfaceProxy::Factory factory);
void AddPPB(const char* name, ApiID id, const void* iface);
// Permissions is the type of permission required to access the corresponding
// interface. Currently this must be just one unique permission (rather than
// a bitfield).
void AddPPB(const char* name, ApiID id, const void* iface,
Permission permission);
void AddPPP(const char* name, ApiID id, const void* iface);
// Old-style add functions. These should be removed when the rest of the
// proxies are converted over to using the new system.
void AddPPB(const InterfaceProxy::Info* info);
void AddPPB(const InterfaceProxy::Info* info, Permission perm);
void AddPPP(const InterfaceProxy::Info* info);
PpapiPermissions permissions_;
NameToInterfaceInfoMap name_to_browser_info_;
NameToInterfaceInfoMap name_to_plugin_info_;

@ -60,8 +60,9 @@ InstanceData::~InstanceData() {
}
PluginDispatcher::PluginDispatcher(PP_GetInterface_Func get_interface,
const PpapiPermissions& permissions,
bool incognito)
: Dispatcher(get_interface),
: Dispatcher(get_interface, permissions),
plugin_delegate_(NULL),
received_preferences_(false),
plugin_dispatcher_id_(0),

@ -83,8 +83,18 @@ class PPAPI_PROXY_EXPORT PluginDispatcher
// will be automatically called when requested by the renderer side. The
// module ID will be set upon receipt of the InitializeModule message.
//
// Note about permissions: On the plugin side, the dispatcher and the plugin
// run in the same address space (including in nacl). This means that the
// permissions here are subject to malicious modification and bypass, and
// an exploited or malicious plugin could send any IPC messages and just
// bypass the permissions. All permissions must be checked "for realz" in the
// host process when receiving messages. We check them on the plugin side
// primarily to keep honest plugins honest, especially with respect to
// dev interfaces that they "shouldn't" be using.
//
// You must call InitPluginWithChannel after the constructor.
PluginDispatcher(PP_GetInterface_Func get_interface,
const PpapiPermissions& permissions,
bool incognito);
virtual ~PluginDispatcher();

@ -76,6 +76,7 @@ class PpapiDispatcher : public ProxyChannel,
private:
void OnMsgCreateNaClChannel(int renderer_id,
const ppapi::PpapiPermissions& permissions,
bool incognito,
SerializedHandle handle);
void OnPluginDispatcherMessageReceived(const IPC::Message& msg);
@ -182,11 +183,18 @@ bool PpapiDispatcher::OnMessageReceived(const IPC::Message& msg) {
return true;
}
void PpapiDispatcher::OnMsgCreateNaClChannel(int renderer_id,
bool incognito,
SerializedHandle handle) {
void PpapiDispatcher::OnMsgCreateNaClChannel(
int renderer_id,
const ppapi::PpapiPermissions& permissions,
bool incognito,
SerializedHandle handle) {
// Tell the process-global GetInterface which interfaces it can return to the
// plugin.
ppapi::proxy::InterfaceList::SetProcessGlobalPermissions(
permissions);
PluginDispatcher* dispatcher =
new PluginDispatcher(::PPP_GetInterface, incognito);
new PluginDispatcher(::PPP_GetInterface, permissions, incognito);
// The channel handle's true name is not revealed here.
IPC::ChannelHandle channel_handle("nacl", handle.descriptor());
if (!dispatcher->InitPluginWithChannel(this, channel_handle, false)) {

@ -259,7 +259,9 @@ IPC_STRUCT_TRAITS_END()
// These are from the browser to the plugin.
// Loads the given plugin.
IPC_MESSAGE_CONTROL1(PpapiMsg_LoadPlugin, FilePath /* path */)
IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin,
FilePath /* path */,
ppapi::PpapiPermissions /* permissions */)
// Creates a channel to talk to a renderer. The plugin will respond with
// PpapiHostMsg_ChannelCreated.
@ -270,8 +272,9 @@ IPC_MESSAGE_CONTROL2(PpapiMsg_CreateChannel,
// Creates a channel to talk to a renderer. This message is only used by the
// NaCl IPC proxy. It is intercepted by NaClIPCAdapter, which creates the
// actual channel and rewrites the message for the untrusted side.
IPC_MESSAGE_CONTROL3(PpapiMsg_CreateNaClChannel,
IPC_MESSAGE_CONTROL4(PpapiMsg_CreateNaClChannel,
int /* renderer_id */,
ppapi::PpapiPermissions /* permissions */,
bool /* incognito */,
ppapi::proxy::SerializedHandle /* channel_handle */)

@ -312,6 +312,29 @@ void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Log(
std::string* l) {
}
// ppapi::PpapiPermissions -----------------------------------------------------
void ParamTraits<ppapi::PpapiPermissions>::Write(Message* m,
const param_type& p) {
ParamTraits<uint32_t>::Write(m, p.GetBits());
}
// static
bool ParamTraits<ppapi::PpapiPermissions>::Read(const Message* m,
PickleIterator* iter,
param_type* r) {
uint32_t bits;
if (!ParamTraits<uint32_t>::Read(m, iter, &bits))
return false;
*r = ppapi::PpapiPermissions(bits);
return true;
}
// static
void ParamTraits<ppapi::PpapiPermissions>::Log(const param_type& p,
std::string* l) {
}
// SerializedHandle ------------------------------------------------------------
// static

@ -14,6 +14,7 @@
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "ppapi/shared_impl/ppb_file_ref_shared.h"
struct PP_FileInfo;
@ -156,6 +157,14 @@ struct PPAPI_PROXY_EXPORT ParamTraits< std::vector<
static void Log(const param_type& p, std::string* l);
};
template<>
struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PpapiPermissions> {
typedef ppapi::PpapiPermissions param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
#if !defined(OS_NACL) && !defined(NACL_WIN64)
template<>
struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedFlashMenu> {

@ -169,6 +169,7 @@ void PluginProxyTestHarness::SetUpHarness() {
plugin_dispatcher_.reset(new PluginDispatcher(
&MockGetInterface,
PpapiPermissions(),
false));
plugin_dispatcher_->InitWithTestSink(&sink());
plugin_dispatcher_->DidCreateInstance(pp_instance());
@ -195,6 +196,7 @@ void PluginProxyTestHarness::SetUpHarnessWithChannel(
plugin_dispatcher_.reset(new PluginDispatcher(
&MockGetInterface,
PpapiPermissions(),
false));
plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
channel_handle,
@ -314,7 +316,8 @@ void HostProxyTestHarness::SetUpHarness() {
host_dispatcher_.reset(new HostDispatcher(
pp_module(),
&MockGetInterface,
status_receiver_.release()));
status_receiver_.release(),
PpapiPermissions()));
host_dispatcher_->InitWithTestSink(&sink());
HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}
@ -333,7 +336,8 @@ void HostProxyTestHarness::SetUpHarnessWithChannel(
host_dispatcher_.reset(new HostDispatcher(
pp_module(),
&MockGetInterface,
status_receiver_.release()));
status_receiver_.release(),
PpapiPermissions()));
ppapi::Preferences preferences;
host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle,
is_client, preferences);

@ -102,6 +102,9 @@ PP_Resource PPB_Flash_Menu_Proxy::CreateProxyResource(
}
bool PPB_Flash_Menu_Proxy::OnMessageReceived(const IPC::Message& msg) {
if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
return false;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Menu_Proxy, msg)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMenu_Create,

@ -96,6 +96,9 @@ PP_Resource PPB_Flash_MessageLoop_Proxy::CreateProxyResource(
}
bool PPB_Flash_MessageLoop_Proxy::OnMessageReceived(const IPC::Message& msg) {
if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
return false;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PPB_Flash_MessageLoop_Proxy, msg)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMessageLoop_Create,

@ -88,6 +88,9 @@ const PPB_Flash_Print_1_0* PPB_Flash_Proxy::GetFlashPrintInterface() {
}
bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) {
if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
return false;
// Prevent the dispatcher from going away during a call to Navigate.
// This must happen OUTSIDE of OnMsgNavigate since the handling code use
// the dispatcher upon return of the function (sending the reply message).

@ -4,7 +4,9 @@
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "ppapi/shared_impl/ppapi_switches.h"
namespace ppapi {
@ -19,10 +21,22 @@ PpapiPermissions::~PpapiPermissions() {
// static
PpapiPermissions PpapiPermissions::AllPermissions() {
return PpapiPermissions(
PERMISSION_DEV |
PERMISSION_PRIVATE |
PERMISSION_BYPASS_USER_GESTURE);
return PpapiPermissions(PERMISSION_ALL_BITS);
}
// static
PpapiPermissions PpapiPermissions::GetForCommandLine(uint32 base_perms) {
uint32 additional_permissions = 0;
#if !defined(OS_NACL)
// Testing permissions. The testing flag implies all permissions since the
// test plugin needs to test all interfaces.
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnablePepperTesting))
additional_permissions |= ppapi::PERMISSION_ALL_BITS;
#endif
return PpapiPermissions(base_perms | additional_permissions);
}
bool PpapiPermissions::HasPermission(Permission perm) const {
@ -31,6 +45,8 @@ bool PpapiPermissions::HasPermission(Permission perm) const {
// represented in the future so don't want callers making assumptions about
// bits.
uint32 perm_int = static_cast<uint32>(perm);
if (!perm_int)
return true; // You always have "no permission".
DCHECK((perm_int & (perm_int - 1)) == 0);
return !!(permissions_ & perm_int);
}

@ -11,17 +11,34 @@
namespace ppapi {
enum Permission {
// Placeholder/uninitialized permission.
PERMISSION_NONE = 0,
// Allows access to dev interfaces.
PERMISSION_DEV = 1 << 0,
// Allows access to Browser-internal interfaces.
PERMISSION_PRIVATE = 1 << 2,
PERMISSION_PRIVATE = 1 << 1,
// Allows ability to bypass user-gesture checks for showing things like
// file select dialogs.
PERMISSION_BYPASS_USER_GESTURE = 1 << 3,
PERMISSION_BYPASS_USER_GESTURE = 1 << 2,
// NOTE: If you add stuff be sure to update AllPermissions().
// Testing-only interfaces.
PERMISSION_TESTING = 1 << 3,
// Flash-related interfaces.
PERMISSION_FLASH = 1 << 4,
// NOTE: If you add stuff be sure to update PERMISSION_ALL_BITS.
// Meta permission for initializing plugins registered on the command line
// that get all permissions.
PERMISSION_ALL_BITS = PERMISSION_DEV |
PERMISSION_PRIVATE |
PERMISSION_BYPASS_USER_GESTURE |
PERMISSION_TESTING |
PERMISSION_FLASH
};
class PPAPI_SHARED_EXPORT PpapiPermissions {
@ -38,8 +55,16 @@ class PPAPI_SHARED_EXPORT PpapiPermissions {
// and manually registered plugins.
static PpapiPermissions AllPermissions();
// Returns the effective permissions given the "base" permissions granted
// to the given plugin and the current command line flags, which may enable
// more features.
static PpapiPermissions GetForCommandLine(uint32 base_perms);
bool HasPermission(Permission perm) const;
// Returns the internal permission bits. Use for serialization only.
uint32 GetBits() const { return permissions_; }
private:
uint32 permissions_;

@ -0,0 +1,12 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/shared_impl/ppapi_switches.h"
namespace switches {
// Enables the testing interface for PPAPI.
const char kEnablePepperTesting[] = "enable-pepper-testing";
} // namespace switches

@ -0,0 +1,16 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_SHARED_IMPL_PPAPI_SWITCHES_H_
#define PPAPI_SHARED_IMPL_PPAPI_SWITCHES_H_
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace switches {
PPAPI_SHARED_EXPORT extern const char kEnablePepperTesting[];
} // namespace switches
#endif // PPAPI_SHARED_IMPL_PPAPI_SWITCHES_H_

@ -6,9 +6,6 @@
namespace switches {
// Enables the testing interface for PPAPI.
const char kEnablePepperTesting[] = "enable-pepper-testing";
// Dumps extra logging about plugin loading to the log file.
const char kDebugPluginLoading[] = "debug-plugin-loading";

@ -12,7 +12,6 @@ namespace switches {
WEBKIT_PLUGINS_EXPORT extern const char kDebugPluginLoading[];
WEBKIT_PLUGINS_EXPORT extern const char kDisablePepper3dForUntrustedUse[];
WEBKIT_PLUGINS_EXPORT extern const char kEnablePepperTesting[];
WEBKIT_PLUGINS_EXPORT extern const char kPpapiFlashArgs[];
#if defined(OS_WIN)

@ -99,6 +99,7 @@
#include "ppapi/c/trusted/ppb_image_data_trusted.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/shared_impl/callback_tracker.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h"
#include "ppapi/shared_impl/ppb_opengles2_shared.h"
#include "ppapi/shared_impl/ppb_var_shared.h"