diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-02 18:12:41 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-02 18:12:41 +0000 |
commit | 195d4cde0da1d590ea978da9e532feceebe12ec1 (patch) | |
tree | f93460315e38383d74dcb46590275ef989b40caa /ppapi | |
parent | 8a56410423d622cf586c7587f6c3634d391254d7 (diff) | |
download | chromium_src-195d4cde0da1d590ea978da9e532feceebe12ec1.zip chromium_src-195d4cde0da1d590ea978da9e532feceebe12ec1.tar.gz chromium_src-195d4cde0da1d590ea978da9e532feceebe12ec1.tar.bz2 |
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
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/ppapi_shared.gypi | 2 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.cc | 7 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.h | 11 | ||||
-rw-r--r-- | ppapi/proxy/host_dispatcher.cc | 5 | ||||
-rw-r--r-- | ppapi/proxy/host_dispatcher.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/interface_list.cc | 95 | ||||
-rw-r--r-- | ppapi/proxy/interface_list.h | 38 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.cc | 3 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.h | 10 | ||||
-rw-r--r-- | ppapi/proxy/plugin_main_nacl.cc | 16 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 7 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_param_traits.cc | 23 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_param_traits.h | 9 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_proxy_test.cc | 8 | ||||
-rw-r--r-- | ppapi/proxy/ppb_flash_menu_proxy.cc | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppb_flash_message_loop_proxy.cc | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppb_flash_proxy.cc | 3 | ||||
-rw-r--r-- | ppapi/shared_impl/ppapi_permissions.cc | 24 | ||||
-rw-r--r-- | ppapi/shared_impl/ppapi_permissions.h | 31 | ||||
-rw-r--r-- | ppapi/shared_impl/ppapi_switches.cc | 12 | ||||
-rw-r--r-- | ppapi/shared_impl/ppapi_switches.h | 16 |
21 files changed, 266 insertions, 63 deletions
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi index 25d0228..e43870c 100644 --- a/ppapi/ppapi_shared.gypi +++ b/ppapi/ppapi_shared.gypi @@ -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', diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc index 3ef2c27..3b18932 100644 --- a/ppapi/proxy/dispatcher.cc +++ b/ppapi/proxy/dispatcher.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() { diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h index 3bd8598..7bb2c7e 100644 --- a/ppapi/proxy/dispatcher.h +++ b/ppapi/proxy/dispatcher.h @@ -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); }; diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc index 0170edb..835fd62 100644 --- a/ppapi/proxy/host_dispatcher.cc +++ b/ppapi/proxy/host_dispatcher.cc @@ -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), diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h index da64467..98a7ad5 100644 --- a/ppapi/proxy/host_dispatcher.h +++ b/ppapi/proxy/host_dispatcher.h @@ -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. diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 99b846f..5d94635 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -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) { diff --git a/ppapi/proxy/interface_list.h b/ppapi/proxy/interface_list.h index 3863234..9ef91dc 100644 --- a/ppapi/proxy/interface_list.h +++ b/ppapi/proxy/interface_list.h @@ -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_; diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc index 8dbca8d..51a8ff2 100644 --- a/ppapi/proxy/plugin_dispatcher.cc +++ b/ppapi/proxy/plugin_dispatcher.cc @@ -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), diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h index 66b5e2d..fe2999c 100644 --- a/ppapi/proxy/plugin_dispatcher.h +++ b/ppapi/proxy/plugin_dispatcher.h @@ -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(); diff --git a/ppapi/proxy/plugin_main_nacl.cc b/ppapi/proxy/plugin_main_nacl.cc index aae60b0..1b5ff55 100644 --- a/ppapi/proxy/plugin_main_nacl.cc +++ b/ppapi/proxy/plugin_main_nacl.cc @@ -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)) { diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index bd24ab2..ba99e8c 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -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 */) diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc index 2858eaf..1c1ddbe 100644 --- a/ppapi/proxy/ppapi_param_traits.cc +++ b/ppapi/proxy/ppapi_param_traits.cc @@ -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 diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h index 70600d3..13f7351 100644 --- a/ppapi/proxy/ppapi_param_traits.h +++ b/ppapi/proxy/ppapi_param_traits.h @@ -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> { diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc index be75083..bf139bb 100644 --- a/ppapi/proxy/ppapi_proxy_test.cc +++ b/ppapi/proxy/ppapi_proxy_test.cc @@ -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); diff --git a/ppapi/proxy/ppb_flash_menu_proxy.cc b/ppapi/proxy/ppb_flash_menu_proxy.cc index 1c919a6..9cc8d63 100644 --- a/ppapi/proxy/ppb_flash_menu_proxy.cc +++ b/ppapi/proxy/ppb_flash_menu_proxy.cc @@ -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, diff --git a/ppapi/proxy/ppb_flash_message_loop_proxy.cc b/ppapi/proxy/ppb_flash_message_loop_proxy.cc index 2124e5a..c4d4ce1 100644 --- a/ppapi/proxy/ppb_flash_message_loop_proxy.cc +++ b/ppapi/proxy/ppb_flash_message_loop_proxy.cc @@ -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, diff --git a/ppapi/proxy/ppb_flash_proxy.cc b/ppapi/proxy/ppb_flash_proxy.cc index a8767f7..c45318c 100644 --- a/ppapi/proxy/ppb_flash_proxy.cc +++ b/ppapi/proxy/ppb_flash_proxy.cc @@ -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). diff --git a/ppapi/shared_impl/ppapi_permissions.cc b/ppapi/shared_impl/ppapi_permissions.cc index d92f6ba..7b833238 100644 --- a/ppapi/shared_impl/ppapi_permissions.cc +++ b/ppapi/shared_impl/ppapi_permissions.cc @@ -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); } diff --git a/ppapi/shared_impl/ppapi_permissions.h b/ppapi/shared_impl/ppapi_permissions.h index 8456fb7..fb82cfc 100644 --- a/ppapi/shared_impl/ppapi_permissions.h +++ b/ppapi/shared_impl/ppapi_permissions.h @@ -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, + + // Testing-only interfaces. + PERMISSION_TESTING = 1 << 3, + + // Flash-related interfaces. + PERMISSION_FLASH = 1 << 4, - // NOTE: If you add stuff be sure to update AllPermissions(). + // 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_; diff --git a/ppapi/shared_impl/ppapi_switches.cc b/ppapi/shared_impl/ppapi_switches.cc new file mode 100644 index 0000000..84ba250 --- /dev/null +++ b/ppapi/shared_impl/ppapi_switches.cc @@ -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 diff --git a/ppapi/shared_impl/ppapi_switches.h b/ppapi/shared_impl/ppapi_switches.h new file mode 100644 index 0000000..a5c8e9d --- /dev/null +++ b/ppapi/shared_impl/ppapi_switches.h @@ -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_ |