DRM VMA Access Management
Subsystems (17)
cover DRM VMA Access Management
Hi
This is the second part of the unified VMA manager. It implements proper access management so applications can map only buffers that they own handles for.
Patches of interest probably are:
#1: Implement VMA access management helpers #9: Make TTM deny unprivileged mmap() calls #10: Do the same for GEM
The remaining patches just hook it up in all drivers.
The implementation is pretty easy. On gem_open_object() drivers add the "struct file*" pointer to the list of allowed open-files of a bo. On gem_close_object() drivers remove it again. For TTM, drivers do this manually as there is no access to TTM bo's from generic GEM code. For GEM, drivers can set DRIVER_GEM_MMAP (copied from airlied's proposal) and GEM core will take care of this.
If we want this to be more uniform, I can add gem_open_object() and gem_close_object() callbacks to all the GEM drivers and call drm_vma_node_allow() and drm_vma_node_revoke() respectively. Just let me know what you think is cleaner.
Cheers
David
David Herrmann (16):
drm/vma: add access management helpers drm/ast: implement mmap access managament drm/cirrus: implement mmap access managament drm/mgag200: implement mmap access managament drm/nouveau: implement mmap access managament drm/radeon: implement mmap access managament drm/qxl: implement mmap access managament drm/vmwgfx: implement mmap access managament drm/ttm: prevent mmap access to unauthorized users drm/gem: implement mmap access management drm/i915: enable GEM mmap access management drm/exynos: enable GEM mmap access management drm/gma500: enable GEM mmap access management drm/omap: enable GEM mmap access management drm/udl: enable GEM mmap access management drm/host1x: enable GEM mmap access management
Documentation/DocBook/drm.tmpl | 13 +++ drivers/gpu/drm/ast/ast_drv.c | 2 + drivers/gpu/drm/ast/ast_drv.h | 4 + drivers/gpu/drm/ast/ast_main.c | 15 +++ drivers/gpu/drm/cirrus/cirrus_drv.h | 4 + drivers/gpu/drm/cirrus/cirrus_main.c | 15 +++ drivers/gpu/drm/drm_gem.c | 37 +++++++- drivers/gpu/drm/drm_vma_manager.c | 155 +++++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 +- drivers/gpu/drm/gma500/psb_drv.c | 3 +- drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 + drivers/gpu/drm/mgag200/mgag200_drv.h | 4 + drivers/gpu/drm/mgag200/mgag200_main.c | 15 +++ drivers/gpu/drm/nouveau/nouveau_gem.c | 19 +++- drivers/gpu/drm/omapdrm/omap_drv.c | 3 +- drivers/gpu/drm/qxl/qxl_gem.c | 7 +- drivers/gpu/drm/radeon/radeon_gem.c | 7 ++ drivers/gpu/drm/ttm/ttm_bo_vm.c | 9 +- drivers/gpu/drm/udl/udl_drv.c | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++--- drivers/gpu/host1x/drm/drm.c | 2 +- include/drm/drmP.h | 1 + include/drm/drm_vma_manager.h | 21 ++++- 24 files changed, 342 insertions(+), 34 deletions(-)
Signature · 1 line
1.8.3.4
PATCH 1/16 drm/vma: add access management helpers
The VMA offset manager uses a device-global address-space. Hence, any user can currently map any offset-node they want. They only need to guess the right offset. If we wanted per open-file offset spaces, we'd either need VM_NONLINEAR mappings or multiple "struct address_space" trees. As both doesn't really scale, we implement access management in the VMA manager itself.
We use an rb-tree to store open-files for each VMA node. On each mmap call, GEM, TTM or the drivers must check whether the current user is allowed to map this file.
We add a separate lock for each node as there is no generic lock available for the caller to protect the node easily.
As we currently don't know whether an object may be used for mmap(), we have to do access management for all objects. If it turns out to slow down handle creation/deletion significantly, we can optimize it in several ways:
- Most times only a single filp is added per bo so we could use a static "struct file *main_filp" which is checked/added/removed first before we fall back to the rbtree+drm_vma_offset_file.
This could be even done lockless with rcu.
- Let user-space pass a hint whether mmap() should be supported on the bo and avoid access-management if not.
- .. there are probably more ideas once we have benchmarks ..
--- drivers/gpu/drm/drm_gem.c | 1 + drivers/gpu/drm/drm_vma_manager.c | 155 ++++++++++++++++++++++++++++++++++++++ include/drm/drm_vma_manager.h | 21 +++++- 3 files changed, 174 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_gem.c +1 -0
@@ -156,6 +156,7 @@ void drm_gem_private_object_init(struct drm_device *dev,kref_init (&obj->refcount);atomic_set (&obj->handle_count,0 ); obj->size = size; +drm_vma_node_reset (&obj->vma_node); }EXPORT_SYMBOL (drm_gem_private_object_init);
drivers/gpu/drm/drm_vma_manager.c +155 -0
170 lines not on this page · raw message
include/drm/drm_vma_manager.h +18 -3
@@ -24,15 +24,24 @@*/ #include <drm/drm_mm.h> +#include <linux/fs.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/rbtree.h> #include <linux/spinlock.h> #include <linux/types.h> +struct drm_vma_offset_file { +struct rb_node vm_rb; +struct file *vm_filp; +unsigned long vm_count; +}; +struct drm_vma_offset_node { +rwlock_t vm_lock;struct drm_mm_node vm_node;struct rb_node vm_rb; +struct rb_root vm_files; };struct drm_vma_offset_manager {
@@ -56,6 +65,11 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,void drm_vma_offset_remove (struct drm_vma_offset_manager *mgr,struct drm_vma_offset_node *node); +int drm_vma_node_allow (struct drm_vma_offset_node *node,struct file *filp); +void drm_vma_node_revoke (struct drm_vma_offset_node *node,struct file *filp); +bool drm_vma_node_is_allowed (struct drm_vma_offset_node *node, +struct file *filp); +/** * drm_vma_offset_exact_lookup() - Look up node by exact address * @mgr: Manager object
@@ -122,9 +136,8 @@ static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *m* drm_vma_node_reset() - Initialize or reset node object * @node: Node to initialize or reset * -* Reset a node to its initial state. This must be called if @node isn't -* already cleared (eg., via kzalloc) before using it with any VMA offset -* manager. +* Reset a node to its initial state. This must be called before using it with +* any VMA offset manager. * * This must not be called on an already allocated node, or you will leak * memory.
@@ -132,6 +145,8 @@ static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *mstatic inline void drm_vma_node_reset (struct drm_vma_offset_node *node) {memset (node,0 ,sizeof (*node)); + node->vm_files =RB_ROOT ; +rwlock_init (&node->vm_lock); }/**
Signature · 1 line
1.8.3.4
PATCH 2/16 drm/ast: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/ast/ast_drv.c | 2 ++ drivers/gpu/drm/ast/ast_drv.h | 4 ++++ drivers/gpu/drm/ast/ast_main.c | 15 +++++++++++++++ 3 files changed, 21 insertions(+)
drivers/gpu/drm/ast/ast_drv.c +2 -0
@@ -214,6 +214,8 @@ static struct drm_driver driver = { .gem_init_object = ast_gem_init_object, .gem_free_object = ast_gem_free_object, + .gem_open_object = ast_gem_open_object, + .gem_close_object = ast_gem_close_object, .dumb_create = ast_dumb_create, .dumb_map_offset = ast_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy,
drivers/gpu/drm/ast/ast_drv.h +4 -0
@@ -325,6 +325,10 @@ extern int ast_dumb_create(struct drm_file *file,extern int ast_gem_init_object (struct drm_gem_object *obj);extern void ast_gem_free_object (struct drm_gem_object *obj); +extern int ast_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv); +extern void ast_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv); extern int ast_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle,
drivers/gpu/drm/ast/ast_main.c +15 -0
@@ -477,6 +477,21 @@ void ast_gem_free_object(struct drm_gem_object *obj)ast_bo_unref (&ast_bo); } +int ast_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct ast_bo *ast_bo =gem_to_ast_bo (obj); + +return drm_vma_node_allow (&ast_bo->bo.vma_node, file_priv->filp); +} + +void ast_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct ast_bo *ast_bo =gem_to_ast_bo (obj); + +drm_vma_node_revoke (&ast_bo->bo.vma_node, file_priv->filp); +}static inline u64 ast_bo_mmap_offset (struct ast_bo *bo) {
Signature · 1 line
1.8.3.4
PATCH 3/16 drm/cirrus: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/cirrus/cirrus_drv.h | 4 ++++ drivers/gpu/drm/cirrus/cirrus_main.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+)
drivers/gpu/drm/cirrus/cirrus_drv.h +4 -0
@@ -193,6 +193,10 @@ int cirrus_device_init(struct cirrus_device *cdev,void cirrus_device_fini (struct cirrus_device *cdev);int cirrus_gem_init_object (struct drm_gem_object *obj);void cirrus_gem_free_object (struct drm_gem_object *obj); +int cirrus_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv); +void cirrus_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv); int cirrus_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle,
drivers/gpu/drm/cirrus/cirrus_main.c +15 -0
@@ -284,6 +284,21 @@ void cirrus_gem_free_object(struct drm_gem_object *obj)cirrus_bo_unref (&cirrus_bo); } +int cirrus_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct cirrus_bo *bo =gem_to_cirrus_bo (obj); + +return drm_vma_node_allow (&bo->bo.vma_node, file_priv->filp); +} + +void cirrus_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct cirrus_bo *bo =gem_to_cirrus_bo (obj); + +drm_vma_node_revoke (&bo->bo.vma_node, file_priv->filp); +}static inline u64 cirrus_bo_mmap_offset (struct cirrus_bo *bo) {
Signature · 1 line
1.8.3.4
PATCH 4/16 drm/mgag200: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 ++ drivers/gpu/drm/mgag200/mgag200_drv.h | 4 ++++ drivers/gpu/drm/mgag200/mgag200_main.c | 15 +++++++++++++++ 3 files changed, 21 insertions(+)
drivers/gpu/drm/mgag200/mgag200_drv.c +2 -0
@@ -102,6 +102,8 @@ static struct drm_driver driver = { .gem_init_object = mgag200_gem_init_object, .gem_free_object = mgag200_gem_free_object, + .gem_open_object = mgag200_gem_open_object, + .gem_close_object = mgag200_gem_close_object, .dumb_create = mgag200_dumb_create, .dumb_map_offset = mgag200_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy,
drivers/gpu/drm/mgag200/mgag200_drv.h +4 -0
@@ -265,6 +265,10 @@ int mgag200_dumb_create(struct drm_file *file,struct drm_device *dev, struct drm_mode_create_dumb *args);void mgag200_gem_free_object (struct drm_gem_object *obj); +int mgag200_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv); +void mgag200_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv); int mgag200_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
drivers/gpu/drm/mgag200/mgag200_main.c +15 -0
@@ -339,6 +339,21 @@ void mgag200_gem_free_object(struct drm_gem_object *obj)mgag200_bo_unref (&mgag200_bo); } +int mgag200_gem_open_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct mgag200_bo *bo =gem_to_mga_bo (obj); + +return drm_vma_node_allow (&bo->bo.vma_node, file_priv->filp); +} + +void mgag200_gem_close_object (struct drm_gem_object *obj, +struct drm_file *file_priv) +{ +struct mgag200_bo *bo =gem_to_mga_bo (obj); + +drm_vma_node_revoke (&bo->bo.vma_node, file_priv->filp); +}static inline u64 mgag200_bo_mmap_offset (struct mgag200_bo *bo) {
Signature · 1 line
1.8.3.4
PATCH 5/16 drm/nouveau: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/nouveau/nouveau_gem.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
drivers/gpu/drm/nouveau/nouveau_gem.c +15 -4
@@ -67,32 +67,41 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)struct nouveau_vma *vma;int ret; + ret =drm_vma_node_allow (&nvbo->bo.vma_node, file_priv->filp); +if (ret) +return ret; +if (!cli->base.vm)return 0 ; ret =ttm_bo_reserve (&nvbo->bo, false, false, false,0 );if (ret) -return ret; + goto err_node; vma =nouveau_bo_vma_find (nvbo, cli->base.vm);if (!vma) { vma =kzalloc (sizeof (*vma),GFP_KERNEL );if (!vma) { ret = -ENOMEM ; - goto out; + goto err_reserve; } ret =nouveau_bo_vma_add (nvbo, cli->base.vm, vma);if (ret) {kfree (vma); - goto out; + goto err_reserve; } }else { vma->refcount++; } -out:ttm_bo_unreserve (&nvbo->bo); +return 0 ; + +err_reserve: +ttm_bo_unreserve (&nvbo->bo); +err_node: +drm_vma_node_revoke (&nvbo->bo.vma_node, file_priv->filp);return ret; }
@@ -139,6 +148,8 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)struct nouveau_vma *vma;int ret; +drm_vma_node_revoke (&nvbo->bo.vma_node, file_priv->filp); +if (!cli->base.vm)return ;
Signature · 1 line
1.8.3.4
PATCH 6/16 drm/radeon: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/radeon/radeon_gem.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/gpu/drm/radeon/radeon_gem.c +7 -0
@@ -147,12 +147,17 @@ int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pristruct radeon_bo_va *bo_va;int r; + r =drm_vma_node_allow (&rbo->tbo.vma_node, file_priv->filp); +if (r) +return r; +if (rdev->family <CHIP_CAYMAN ) {return 0 ; } r =radeon_bo_reserve (rbo, false);if (r) { +drm_vma_node_revoke (&rbo->tbo.vma_node, file_priv->filp);return r; }
@@ -177,6 +182,8 @@ void radeon_gem_object_close(struct drm_gem_object *obj,struct radeon_bo_va *bo_va;int r; +drm_vma_node_revoke (&rbo->tbo.vma_node, file_priv->filp); +if (rdev->family <CHIP_CAYMAN ) {return ; }
Signature · 1 line
1.8.3.4
PATCH 7/16 drm/qxl: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager.
--- drivers/gpu/drm/qxl/qxl_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/qxl/qxl_gem.c +6 -1
@@ -129,12 +129,17 @@ void qxl_gem_object_unpin(struct drm_gem_object *obj)int qxl_gem_object_open (struct drm_gem_object *obj,struct drm_file *file_priv) { -return 0 ; +struct qxl_bo *qobj = obj->driver_private; + +return drm_vma_node_allow (&qobj->tbo.vma_node, file_priv->filp); }void qxl_gem_object_close (struct drm_gem_object *obj,struct drm_file *file_priv) { +struct qxl_bo *qobj = obj->driver_private; + +drm_vma_node_revoke (&qobj->tbo.vma_node, file_priv->filp); }int qxl_gem_init (struct qxl_device *qdev)
Signature · 1 line
1.8.3.4
PATCH 8/16 drm/vmwgfx: implement mmap access managament
In reply to David HerrmannCorrectly allow and revoke buffer access on each open/close via the new VMA offset manager. We also need to make vmw_user_dmabuf_reference() correctly increase the vma-allow counter, but it is unused so remove it instead.
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +17 -12
@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,if (unlikely (ret !=0 )) goto out_no_dmabuf; + ret =drm_vma_node_allow (&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle; rep->map_handle =drm_vma_node_offset_addr (&dma_buf->base.vma_node); rep->cur_gmr_id = handle;
@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ; +drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to vmw_dmabuf_unreference(dma_buf)? */ return ttm_ref_object_base_unref (vmw_fpriv (file_priv)->tfile, arg->handle,TTM_REF_USAGE );
@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,return 0 ; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE ,NULL ); -} -/* * Stream management */
Signature · 1 line
1.8.3.4
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
Hi
Quoted 7 lines · David Herrmann
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager. We also need to make
vmw_user_dmabuf_reference()correctly increase the vma-allow counter, but it is unused so remove it instead.Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>
Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
David
Quoted 62 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +17
-13@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,if (unlikely (ret !=0 )) goto out_no_dmabuf; + ret =drm_vma_node_allow (&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle; rep->map_handle =drm_vma_node_offset_addr (&dma_buf->base.vma_node); rep->cur_gmr_id = handle;@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ; +drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to vmw_dmabuf_unreference(dma_buf)? */ return ttm_ref_object_base_unref (vmw_fpriv (file_priv)->tfile, arg->handle,TTM_REF_USAGE );@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,return 0 ; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE ,NULL ); -} -/* * Stream management */ --1.8.3.4
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
(CC'ing the proper people since I'm still on parental leave).
On 08/13/2013 11:44 PM, David Herrmann wrote:
Please see inline comments.
Quoted 5 lines
Hi
Quoted 2 lines · David Herrmann
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager.
I haven't yet had time to check the access policies of the new VMA offset manager, but anything that is identical or stricter than the current vmwgfx verify_access() would be fine. If it's stricter however, we need to double-check backwards user-space compatibility.
Quoted 3 lines
Quoted 3 lines
We also need to make
vmw_user_dmabuf_reference()
correctly increase the vma-allow counter, but it is unused so remove it instead.
IIRC this function or a derivative thereof is used heavily in an upcoming version driver, so if possible, please add a corrected version rather than remove the (currently) unused code. This will trigger a merge error and the upcoming code can be more easily corrected.
Quoted 43 lines
Quoted 3 lines
Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
DavidQuoted 33 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +13
-0@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,if (unlikely (ret !=0 )) goto out_no_dmabuf; + ret =drm_vma_node_allow (&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle; rep->map_handle =drm_vma_node_offset_addr (&dma_buf->base.vma_node); rep->cur_gmr_id = handle;@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ;
Quoted 4 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, · line 537
Quoted 4 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +4
-0+drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to vmw_dmabuf_unreference(dma_buf)? */
No. A ttm ref object is rather similar to a generic GEM object, only that it's generic in the sense that it is not restricted to buffers, and can make any desired object visible to user-space. So translated the below code removes a reference that the arg->handle holds on the "gem" object, potentially destroying the whole object in which the "gem" object is embedded.
Quoted 17 lines
Quoted 17 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-10return ttm_ref_object_base_unref (vmw_fpriv (file_priv)->tfile, arg->handle,TTM_REF_USAGE );@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,return 0 ; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE ,NULL );
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-3-} -/* * Stream management */ --1.8.3.4
Otherwise looks OK to me.
Thanks,
Thomas
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
Hi
Quoted 12 lines · Thomas Hellstrom
(CC'ing the proper people since I'm still on parental leave).
On 08/13/2013 11:44 PM, David Herrmann wrote:
Please see inline comments.
Quoted 5 lines
Hi
Quoted 1 line · David Herrmann
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager.
I haven't yet had time to check the access policies of the new VMA offset manager, but anything that is identical or stricter than the current vmwgfx
verify_access()would be fine. If it's stricter however, we need to double-check backwards user-space compatibility.
My patches make vmw_dmabuf_alloc_ioctl() add the caller's open-file (file*) to the list of allowed users of the new bo. vmw_dmabuf_unref_ioctl() removes it again. I haven't seen any way to pass a user-dmabuf to another user so there is currently at most one user for a vmw_dmabuf. vmw_user_dmabuf_reference() looks like it is intended exactly for this case so it would have to add the file* of the caller to the list of allowed users. I will change that in v2. This means every user who gets a handle for the buffer (like gem_open) will be added to the allowed users. For TTM-object currently only a single user is allowed.
So I replace vmw_user_bo->base.tfile with a list (actually rbtree) of allowed files. So more than one user can have access. This, however, breaks the "shareable" attribute which I wasn't aware of. As far as I can see, "shareable" is only used by vmwgfx_surface.c and can be set by userspace to allow arbitrary processes to map this buffer (sounds like a security issue similar to gem flink).
I actually think we can replace the "shareable" attribute with proper access-management in the vma-manager. But first I'd need to know whether "shareable = true" is actually used by vmwgfx user-space and how buffers are shared? Do you simply pass the mmap offset between processes? Or do you pass some handle?
If you really pass mmap offsets in user-space and rely on this, I guess there is no way I can make vmwgfx use the vma-manager access management. I will have to find a way to work around it or move the "shareable" flag to ttm_bo.
Quoted 9 lines
Quoted 4 lines
Quoted 4 lines
We also need to make
vmw_user_dmabuf_reference()
correctly increase the vma-allow counter, but it is unused so remove it instead.IIRC this function or a derivative thereof is used heavily in an upcoming version driver, so if possible, please add a corrected version rather than remove the (currently) unused code. This will trigger a merge error and the upcoming code can be more easily corrected.
I will do so.
Quoted 51 lines
Quoted 51 lines
Quoted 4 lines
Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
DavidQuoted 39 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +6
-0@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev,void *data, if (unlikely(ret != 0)) goto out_no_dmabuf; + ret = drm_vma_node_allow(&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle;rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node); rep->cur_gmr_id = handle;drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +7
-0@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ;
Quoted 13 lines
Quoted 5 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
Quoted 5 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +4
-0+drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to vmw_dmabuf_unreference(dma_buf)? */ No. A ttm ref object is rather similar to a generic GEM object, only that it's generic in the sense that it is not restricted to buffers, and can make any desired object visible to user-space. So translated the below code removes a reference that the
arg->handleholds on the "gem" object, potentially destroying the whole object in which the "gem" object is embedded.
So I actually need both lookups, vmw_user_dmabuf_lookup() and the lookup in ttm_ref_object_base_unref()? Ugh.. but ok, I will leave the function then as it is now but remove the comment.
Quoted 22 lines
Quoted 22 lines
Quoted 22 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-0return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,arg->handle, TTM_REF_USAGE);drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-12@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, return 0; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE , NULL); -} -
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-0/* * Stream management
*/
--
1.8.3.4Otherwise looks OK to me.
Thanks!
David
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
Quoted 32 lines · David Herrmann
Hi
Quoted 11 lines · Thomas Hellstrom
(CC'ing the proper people since I'm still on parental leave).
On 08/13/2013 11:44 PM, David Herrmann wrote:
Please see inline comments.
Quoted 4 lines
Hi
On Tue, Aug 13, 2013 at 9:38 PM, David Herrmann <[email protected]> wrote:
Quoted 7 lines
Quoted 2 lines
Quoted 2 lines
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager.
I haven't yet had time to check the access policies of the new VMA offset manager, but anything that is identical or stricter than the current vmwgfx
verify_access()would be fine. If it's stricter however, we need to double-check backwards user-space compatibility.My patches make
vmw_dmabuf_alloc_ioctl()add the caller's open-file (file*) to the list of allowed users of the new bo.vmw_dmabuf_unref_ioctl()removes it again. I haven't seen any way to pass a user-dmabuf to another user so there is currently at most one user for avmw_dmabuf.vmw_user_dmabuf_reference()looks like it is intended exactly for this case so it would have to add the file* of the caller to the list of allowed users. I will change that in v2. This means every user who gets a handle for the buffer (likegem_open) will be added to the allowed users. For TTM-object currently only a single user is allowed.
Quoted 11 lines
So I replace
vmw_user_bo->base.tfilewith a list (actually rbtree) of allowed files. So more than one user can have access. This, however, breaks the "shareable" attribute which I wasn't aware of. As far as I can see, "shareable" is only used byvmwgfx_surface.cand can be set by userspace to allow arbitrary processes to map this buffer (sounds like a security issue similar to gem flink).
I actually think we can replace the "shareable" attribute with proper access-management in the vma-manager. But first I'd need to know whether "shareable = true" is actually used by vmwgfx user-space and how buffers are shared? Do you simply pass the mmap offset between processes? Or do you pass some handle?
Buffer- and surface sharing is done by passing an opaque (not mmap) handle. A process intending to map the shared buffer must obtain the map offset through a vmw_user_dmabuf_reference() call, and that only works if the buffer is "shareable". mmap offsets are never passed between processes, but valid only if obtained directly from the kernel driver.
This means that currently buffer mapping should have the same access restriction as the X server imposes on DRI clients; If a process is allowed to open the drm device, it also has map access to all "shareable" objects, which is a security hole in the sense that verify_access() should really check that the caller, if not the buffer owner, is also authenticated.
The reason verify_access() is there is to make the TTM buffer object transparent to how it is exported to user space (GEM or TTM objects). Apparently the GEM TTM drivers have ignored this hook for some unknown reason.
Some ideas:
1) Rather than having a list of allowable files on each buffer object, perhaps we should have a user and a group and a set of permissions (for user, group and system) more like how files are handled?
2) Rather than imposing a security policy in the vma manager, could we perhaps have a set a utility functions that are called through verify_access(). Each driver could then have a wrapper to gather the needed information and hand it over to the VMA manager?
Quoted 75 lines
If you really pass mmap offsets in user-space and rely on this, I guess there is no way I can make vmwgfx use the vma-manager access management. I will have to find a way to work around it or move the "shareable" flag to
ttm_bo.Quoted 7 lines
Quoted 3 lines
Quoted 3 lines
We also need to make
vmw_user_dmabuf_reference()
correctly increase the vma-allow counter, but it is unused so remove it instead.IIRC this function or a derivative thereof is used heavily in an upcoming version driver, so if possible, please add a corrected version rather than remove the (currently) unused code. This will trigger a merge error and the upcoming code can be more easily corrected.
I will do so.
Quoted 48 lines
Quoted 48 lines
Quoted 2 lines
Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
DavidQuoted 39 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +6
-0@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev,void *data, if (unlikely(ret != 0)) goto out_no_dmabuf; + ret = drm_vma_node_allow(&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle;rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node); rep->cur_gmr_id = handle;drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +7
-0@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ;Quoted 12 lines
Quoted 5 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
Quoted 5 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +4
-0+drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to vmw_dmabuf_unreference(dma_buf)? */ No. A ttm ref object is rather similar to a generic GEM object, only that it's generic in the sense that it is not restricted to buffers, and can make any desired object visible to user-space. So translated the below code removes a reference that the
arg->handleholds on the "gem" object, potentially destroying the whole object in which the "gem" object is embedded.
Quoted 3 lines
So I actually need both lookups,
vmw_user_dmabuf_lookup()and the lookup inttm_ref_object_base_unref()? Ugh.. but ok, I will leave the function then as it is now but remove the comment.
Yes. This seems odd, but IIRC the lookups are from different hash tables. The unref() call makes a lookup in a hash table private to the file.
Quoted 31 lines
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-0return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,arg->handle, TTM_REF_USAGE);drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-11@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, return 0; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE , NULL); -}Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-1-/* * Stream management
*/
--
1.8.3.4Otherwise looks OK to me.
Thanks!
David
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
Hi
Quoted 53 lines · Thomas Hellstrom
Quoted 39 lines · David Herrmann
Hi
Quoted 17 lines · Thomas Hellstrom
(CC'ing the proper people since I'm still on parental leave).
On 08/13/2013 11:44 PM, David Herrmann wrote:
Please see inline comments.
Quoted 7 lines
Hi
Quoted 3 lines · David Herrmann
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager.
Quoted 5 lines
I haven't yet had time to check the access policies of the new VMA offset manager, but anything that is identical or stricter than the current vmwgfx
verify_access()would be fine. If it's stricter however, we need to double-check backwards user-space compatibility.My patches make
vmw_dmabuf_alloc_ioctl()add the caller's open-file (file*) to the list of allowed users of the new bo.vmw_dmabuf_unref_ioctl()removes it again. I haven't seen any way to pass a user-dmabuf to another user so there is currently at most one user for avmw_dmabuf.vmw_user_dmabuf_reference()looks like it is intended exactly for this case so it would have to add the file* of the caller to the list of allowed users. I will change that in v2. This means every user who gets a handle for the buffer (likegem_open) will be added to the allowed users. For TTM-object currently only a single user is allowed.Quoted 11 lines
So I replace
vmw_user_bo->base.tfilewith a list (actually rbtree) of allowed files. So more than one user can have access. This, however, breaks the "shareable" attribute which I wasn't aware of. As far as I can see, "shareable" is only used byvmwgfx_surface.cand can be set by userspace to allow arbitrary processes to map this buffer (sounds like a security issue similar to gem flink).
I actually think we can replace the "shareable" attribute with proper access-management in the vma-manager. But first I'd need to know whether "shareable = true" is actually used by vmwgfx user-space and how buffers are shared? Do you simply pass the mmap offset between processes? Or do you pass some handle?
Quoted 5 lines
Buffer- and surface sharing is done by passing an opaque (not mmap) handle. A process intending to map the shared buffer must obtain the map offset through a
vmw_user_dmabuf_reference()call, and that only works if the buffer is "shareable".
Ugh? That's not true. At least in upstream vmwgfx vmw_user_dmabuf_reference() is unused. Maybe you have access to some newer codebase? Anyway, I can easily make this function call drm_vma_node_allow() and then newer vmwgfx additions will work just fine. This means, every user who calls vmw_user_dmabuf_reference() will then also be allowed to mmap that buffer. But users who do not own a handle (that is, they didn't call vmw_user_dmabuf_reference() or they dropped the reference via vmw_user_dmabuf_unref_ioctl()) will get -EACCES if they try to mmap the buffer.
This is an extension to how it currently works, so I doubt that it breaks any user-space. Is that fine for vmwgfx?
Quoted 3 lines
mmap offsets are never passed between processes, but valid only if obtained directly
from the kernel driver.
Good to hear. That means this patch doesn't break any existing userspace.
Quoted 8 lines
This means that currently buffer mapping should have the same access restriction as the
X server imposes on DRI clients; If a process is allowed to open the drm device, it also has
map access to all "shareable" objects, which is a security hole in the sense thatverify_access()should
really check that the caller, if not the buffer owner, is also authenticated.
I actually don't care for DRI. This series tries to fix exactly that. I don't want that. Users with DRM access shouldn't be able to map arbitrary buffers. Instead, users should only be able to map buffers that they own a handle for. Access management for handles is an orthogonal problem that this series does not change. dma-buf does a pretty good job there, anyway.
Quoted 5 lines
The reason
verify_access()is there is to make the TTM buffer object transparent to how it is exported
to user space (GEM or TTM objects). Apparently the GEM TTM drivers have ignored this hook for some unknown
reason.
I don't think that we need any extended access-management here. Why would we ever need different access-modes for mmap than for handles? This series reduces mmap() access-management to handle-access-management. That is, the right to mmap() a buffer is now bound to a buffer handle. If you don't own a handle, you cannot mmap the buffer. But if you own a handle, you're always allowed to mmap the buffer. I think this should be the policy to go for, or am I missing something?
That's also why I think verify_access() is not needed at all. Drivers shouldn't care for mmap() access, instead they should take care only privileged users get handles (whatever they do to guarantee that, gem-flink, dma-buf, ...).
Cheers
David
Quoted 140 lines
Some ideas:
1) Rather than having a list of allowable files on each buffer object, perhaps we should have a user and a group and
a set of permissions (for user, group and system) more like how files are handled?2) Rather than imposing a security policy in the vma manager, could we perhaps have a set a utility functions that
are called throughverify_access(). Each driver could then have a wrapper to gather the needed information and
hand it over to the VMA manager?Quoted 84 lines
If you really pass mmap offsets in user-space and rely on this, I guess there is no way I can make vmwgfx use the vma-manager access management. I will have to find a way to work around it or move the "shareable" flag to
ttm_bo.Quoted 10 lines
Quoted 3 lines
Quoted 3 lines
We also need to make
vmw_user_dmabuf_reference()
correctly increase the vma-allow counter, but it is unused so remove it instead.IIRC this function or a derivative thereof is used heavily in an upcoming version driver, so if possible, please add a corrected version rather than
remove the (currently) unused code. This will trigger a merge error and the
upcoming code can be more easily corrected.I will do so.
Quoted 49 lines
Quoted 49 lines
Quoted 2 lines
Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
DavidQuoted 39 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +6
-0@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev,void *data, if (unlikely(ret != 0)) goto out_no_dmabuf; + ret = drm_vma_node_allow(&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle;rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node); rep->cur_gmr_id = handle;drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +7
-0@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ;Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +4
-0+drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to
vmw_dmabuf_unreference(dma_buf)?
*/No. A ttm ref object is rather similar to a generic GEM object, only that it's generic in the sense that it is not restricted to buffers, and can make
any desired object visible to user-space. So translated the below code removes a reference that thearg->handleholds on the "gem" object, potentially destroying the whole object in which the "gem" object is embedded.Quoted 3 lines
So I actually need both lookups,
vmw_user_dmabuf_lookup()and the lookup inttm_ref_object_base_unref()? Ugh.. but ok, I will leave the function then as it is now but remove the comment.Yes. This seems odd, but IIRC the lookups are from different hash tables. The
unref()call
makes a lookup in a hash table private to the file.Quoted 33 lines
Quoted 22 lines
Quoted 22 lines
Quoted 22 lines
return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, arg->handle, TTM_REF_USAGE);drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-11@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, return 0; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE , NULL); -}Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-1-/* * Stream management */--
1.8.3.4Otherwise looks OK to me.
Thanks!
David
Re: [PATCH 08/16] drm/vmwgfx: implement mmap access managament
Quoted 50 lines · David Herrmann
Hi
Quoted 47 lines · Thomas Hellstrom
Quoted 45 lines · David Herrmann
Hi
Quoted 11 lines · Thomas Hellstrom
(CC'ing the proper people since I'm still on parental leave).
On 08/13/2013 11:44 PM, David Herrmann wrote:
Please see inline comments.
Quoted 4 lines
Hi
On Tue, Aug 13, 2013 at 9:38 PM, David Herrmann <[email protected]> wrote:
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
Correctly allow and revoke buffer access on each open/close via the new VMA offset manager.
I haven't yet had time to check the access policies of the new VMA offset manager, but anything that is identical or stricter than the current vmwgfx
verify_access()would be fine. If it's stricter however, we need to double-check backwards user-space compatibility.My patches make
vmw_dmabuf_alloc_ioctl()add the caller's open-file (file*) to the list of allowed users of the new bo.vmw_dmabuf_unref_ioctl()removes it again. I haven't seen any way to pass a user-dmabuf to another user so there is currently at most one user for avmw_dmabuf.vmw_user_dmabuf_reference()looks like it is intended exactly for this case so it would have to add the file* of the caller to the list of allowed users. I will change that in v2. This means every user who gets a handle for the buffer (likegem_open) will be added to the allowed users. For TTM-object currently only a single user is allowed.So I replace
vmw_user_bo->base.tfilewith a list (actually rbtree) of allowed files. So more than one user can have access. This, however, breaks the "shareable" attribute which I wasn't aware of. As far as I can see, "shareable" is only used byvmwgfx_surface.cand can be set by userspace to allow arbitrary processes to map this buffer (sounds like a security issue similar to gem flink).
I actually think we can replace the "shareable" attribute with proper access-management in the vma-manager. But first I'd need to know whether "shareable = true" is actually used by vmwgfx user-space and how buffers are shared? Do you simply pass the mmap offset between processes? Or do you pass some handle?
Quoted 8 lines
Quoted 5 lines
Buffer- and surface sharing is done by passing an opaque (not mmap) handle. A process intending to map the shared buffer must obtain the map offset through a
vmw_user_dmabuf_reference()call, and that only works if the buffer is "shareable".Ugh? That's not true. At least in upstream vmwgfx
vmw_user_dmabuf_reference()is unused. Maybe you have access to some newer codebase?
Yes, this is how TTM buffer management used to work in older TTM drivers and how the codebase for newer device versions will work.
Quoted 10 lines
Anyway, I can easily make this function call
drm_vma_node_allow()and then newer vmwgfx additions will work just fine. This means, every user who callsvmw_user_dmabuf_reference()will then also be allowed to mmap that buffer. But users who do not own a handle (that is, they didn't callvmw_user_dmabuf_reference()or they dropped the reference viavmw_user_dmabuf_unref_ioctl()) will get-EACCESif they try to mmap the buffer.This is an extension to how it currently works, so I doubt that it breaks any user-space. Is that fine for vmwgfx?
Yes, that sounds fine.
Quoted 14 lines
Quoted 4 lines
mmap offsets are never passed between processes, but valid only if obtained directly
from the kernel driver.Good to hear. That means this patch doesn't break any existing userspace.
Quoted 8 lines
This means that currently buffer mapping should have the same access restriction as the
X server imposes on DRI clients; If a process is allowed to open the drm device, it also has
map access to all "shareable" objects, which is a security hole in the sense thatverify_access()should
really check that the caller, if not the buffer owner, is also authenticated.
Quoted 6 lines
I actually don't care for DRI. This series tries to fix exactly that. I don't want that. Users with DRM access shouldn't be able to map arbitrary buffers. Instead, users should only be able to map buffers that they own a handle for. Access management for handles is an orthogonal problem that this series does not change. dma-buf does a pretty good job there, anyway.
Understood.
Quoted 15 lines
Quoted 6 lines
The reason
verify_access()is there is to make the TTM buffer object transparent to how it is exported
to user space (GEM or TTM objects). Apparently the GEM TTM drivers have ignored this hook for some unknown
reason.I don't think that we need any extended access-management here. Why would we ever need different access-modes for mmap than for handles? This series reduces
mmap()access-management to handle-access-management. That is, the right tommap()a buffer is now bound to a buffer handle. If you don't own a handle, you cannot mmap the buffer. But if you own a handle, you're always allowed to mmap the buffer. I think this should be the policy to go for, or am I missing something?
Quoted 4 lines
That's also why I think
verify_access()is not needed at all. Drivers shouldn't care formmap()access, instead they should take care only privileged users get handles (whatever they do to guarantee that, gem-flink, dma-buf, ...).
Sounds fair enough.
Thanks,
Thomas
Quoted 134 lines
Cheers
DavidQuoted 131 lines
Some ideas:
1) Rather than having a list of allowable files on each buffer object, perhaps we should have a user and a group and
a set of permissions (for user, group and system) more like how files are handled?2) Rather than imposing a security policy in the vma manager, could we perhaps have a set a utility functions that
are called throughverify_access(). Each driver could then have a wrapper to gather the needed information and
hand it over to the VMA manager?Quoted 78 lines
If you really pass mmap offsets in user-space and rely on this, I guess there is no way I can make vmwgfx use the vma-manager access management. I will have to find a way to work around it or move the "shareable" flag to
ttm_bo.Quoted 9 lines
Quoted 3 lines
Quoted 3 lines
We also need to make
vmw_user_dmabuf_reference()
correctly increase the vma-allow counter, but it is unused so remove it instead.IIRC this function or a derivative thereof is used heavily in an upcoming version driver, so if possible, please add a corrected version rather than
remove the (currently) unused code. This will trigger a merge error and the
upcoming code can be more easily corrected.I will do so.
Quoted 48 lines
Quoted 48 lines
Quoted 2 lines
Cc Thomas Hellstrom <[email protected]>Signed-off-by David Herrmann <[email protected]>Just as a hint, this patch would allow to remove the "->access_verify()" callback in vmwgfx. No other driver uses it, afaik. I will try to add this in v2.
Regards
DavidQuoted 39 lines
--- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +6
-0@@ -499,6 +499,12 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev,void *data, if (unlikely(ret != 0)) goto out_no_dmabuf; + ret = drm_vma_node_allow(&dma_buf->base.vma_node, file_priv->filp); +if (ret) { +vmw_dmabuf_unreference (&dma_buf); + goto out_no_dmabuf; + } + rep->handle = handle;rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node); rep->cur_gmr_id = handle;drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +7
-0@@ -517,7 +523,18 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, {struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; +struct ttm_object_file *tfile =vmw_fpriv (file_priv)->tfile; +struct vmw_dma_buffer *dma_buf; +int ret; + + ret =vmw_user_dmabuf_lookup (tfile, arg->handle, &dma_buf); +if (ret) +return -EINVAL ;Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +4
-0+drm_vma_node_revoke (&dma_buf->base.vma_node, file_priv->filp); +vmw_dmabuf_unreference (&dma_buf); + +/* FIXME: is this equivalent to
vmw_dmabuf_unreference(dma_buf)?
*/No. A ttm ref object is rather similar to a generic GEM object, only that it's generic in the sense that it is not restricted to buffers, and can make
any desired object visible to user-space. So translated the below code removes a reference that thearg->handleholds on the "gem" object, potentially destroying the whole object in which the "gem" object is embedded.Quoted 3 lines
So I actually need both lookups,
vmw_user_dmabuf_lookup()and the lookup inttm_ref_object_base_unref()? Ugh.. but ok, I will leave the function then as it is now but remove the comment.Yes. This seems odd, but IIRC the lookups are from different hash tables. The
unref()call
makes a lookup in a hash table private to the file.Quoted 31 lines
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, arg->handle, TTM_REF_USAGE);drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-11@@ -551,18 +568,6 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, return 0; } -int vmw_user_dmabuf_reference (struct ttm_object_file *tfile, -struct vmw_dma_buffer *dma_buf) -{ -struct vmw_user_dma_buffer *user_bo; - -if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) -return -EINVAL ; - - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); -return ttm_ref_object_add (tfile, &user_bo->base,TTM_REF_USAGE , NULL); -}Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0
-1-/* * Stream management */--
1.8.3.4Otherwise looks OK to me.
Thanks!
David
PATCH 9/16 drm/ttm: prevent mmap access to unauthorized users
In reply to David HerrmannIf a user does not have access to a given buffer, we must not allow them to mmap it. Otherwise, users could "guess" the buffer offsets of other users and get access to the buffer.
Similar to mmap(), we also fix ttm_bo_io() which is the backend for read() and write() syscalls. It's currently unused, though.
All TTM drivers already use the new VMA offset manager access management so we can enable TTM mmap access management now.
--- drivers/gpu/drm/ttm/ttm_bo_vm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/gpu/drm/ttm/ttm_bo_vm.c +5 -4
@@ -219,7 +219,8 @@ static const struct vm_operations_struct ttm_bo_vm_ops = { .close = ttm_bo_vm_close }; -static struct ttm_buffer_object *ttm_bo_vm_lookup (struct ttm_bo_device *bdev, +static struct ttm_buffer_object *ttm_bo_vm_lookup (struct file *filp, +struct ttm_bo_device *bdev,unsigned long offset,unsigned long pages) {
@@ -229,7 +230,7 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev,drm_vma_offset_lock_lookup (&bdev->vma_manager); node =drm_vma_offset_lookup_locked (&bdev->vma_manager, offset, pages); -if (likely (node)) { +if (likely (node) &&drm_vma_node_is_allowed (node, filp)) { bo = container_of(node, struct ttm_buffer_object, vma_node);if (!kref_get_unless_zero (&bo->kref)) bo =NULL ;
@@ -250,7 +251,7 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,struct ttm_buffer_object *bo;int ret; - bo =ttm_bo_vm_lookup (bdev, vma->vm_pgoff,vma_pages (vma)); + bo =ttm_bo_vm_lookup (filp, bdev, vma->vm_pgoff,vma_pages (vma));if (unlikely (!bo))return -EINVAL ;
@@ -310,7 +311,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,bool no_wait = false;bool dummy; - bo =ttm_bo_vm_lookup (bdev, dev_offset,1 ); + bo =ttm_bo_vm_lookup (filp, bdev, dev_offset,1 );if (unlikely (bo ==NULL ))return -EFAULT ;
Signature · 1 line
1.8.3.4
PATCH 10/16 drm/gem: implement mmap access management
In reply to David HerrmannImplement automatic access management for mmap offsets for all GEM drivers. This prevents user-space applications from "guessing" GEM BO offsets and accessing buffers which they don't own.
TTM drivers or other modesetting drivers with custom mm handling might make use of GEM but don't need its mmap helpers. To avoid unnecessary overhead, we limit GEM access management to drivers using DRIVER_GEM_MMAP. So for TTM drivers GEM will not call any *_allow() or *_revoke() helpers.
--- Documentation/DocBook/drm.tmpl | 13 +++++++++++++ drivers/gpu/drm/drm_gem.c | 36 ++++++++++++++++++++++++++++++++---- include/drm/drmP.h | 1 + 3 files changed, 46 insertions(+), 4 deletions(-)
Documentation/DocBook/drm.tmpl +13 -0
@@ -223,6 +223,19 @@ </para></listitem> </varlistentry> <varlistentry> + <term>DRIVER_GEM_MMAP</term> + <listitem><para> + Driver uses default GEM mmap helpers. This flag guarantees that + GEM core takes care of buffer access management and prevents + unprivileged users from mapping random buffers. This flag should + only be set by GEM-only drivers that use the drm_gem_mmap_*() + helpers directly. TTM, on the other hand, takes care of access + management itself, even though drivers might use DRIVER_GEM and + TTM at the same time. See the DRM VMA Offset Manager interface for + more information on buffer mmap() access management. + </para></listitem> + </varlistentry> + <varlistentry> <term>DRIVER_MODESET</term> <listitem><para> Driver supports mode setting interfaces (KMS).
drivers/gpu/drm/drm_gem.c +32 -4
@@ -236,6 +236,9 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)drm_gem_remove_prime_handles (obj, filp); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, filp->filp); +if (dev->driver->gem_close_object) dev->driver->gem_close_object (obj, filp);drm_gem_object_handle_unreference_unlocked (obj);
@@ -288,15 +291,26 @@ drm_gem_handle_create(struct drm_file *file_priv,drm_gem_object_handle_reference (obj); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) { + ret =drm_vma_node_allow (&obj->vma_node, file_priv->filp); +if (ret) + goto err_handle; + } +if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object (obj, file_priv); -if (ret) { -drm_gem_handle_delete (file_priv, *handlep); -return ret; - } +if (ret) + goto err_node; }return 0 ; + +err_node: +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, file_priv->filp); +err_handle: +drm_gem_handle_delete (file_priv, *handlep); +return ret; }EXPORT_SYMBOL (drm_gem_handle_create);
@@ -486,6 +500,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)drm_gem_remove_prime_handles (obj, file_priv); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, file_priv->filp); +if (dev->driver->gem_close_object) dev->driver->gem_close_object (obj, file_priv);
@@ -610,6 +627,10 @@ EXPORT_SYMBOL(drm_gem_vm_close);* the GEM object is not looked up based on its fake offset. To implement the * DRM mmap operation, drivers should use the drm_gem_mmap() function. * +* drm_gem_mmap_obj() assumes the user is granted access to the buffer while +* drm_gem_mmap() prevents unprivileged users from mapping random objects. So +* callers must verify access restrictions before calling this helper. +* * NOTE: This function has to be protected with dev->struct_mutex * * Return 0 or success or -EINVAL if the object size is smaller than the VMA
@@ -658,6 +679,9 @@ EXPORT_SYMBOL(drm_gem_mmap_obj);* Look up the GEM object based on the offset passed in (vma->vm_pgoff will * contain the fake offset we created when the GTT map ioctl was called on * the object) and map it with a call to drm_gem_mmap_obj(). +* +* If the caller is not granted access to the buffer object, the mmap will fail +* with EACCES. Please see DRIVER_GEM_MMAP for more information. */ int drm_gem_mmap (struct file *filp,struct vm_area_struct *vma) {
@@ -678,6 +702,10 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)if (!node) {mutex_unlock (&dev->struct_mutex);return drm_mmap (filp, vma); + }else if (drm_core_check_feature (dev,DRIVER_GEM_MMAP ) && + !drm_vma_node_is_allowed (node, filp)) { +mutex_unlock (&dev->struct_mutex); +return -EACCES ; } obj = container_of(node, struct drm_gem_object, vma_node);
include/drm/drmP.h +1 -0
@@ -152,6 +152,7 @@ int drm_err(const char *func, const char *format, ...);#define DRIVER_GEM 0x1000#define DRIVER_MODESET 0x2000#define DRIVER_PRIME 0x4000 +#define DRIVER_GEM_MMAP 0x8000#define DRIVER_BUS_PCI 0x1#define DRIVER_BUS_PLATFORM 0x2
Signature · 1 line
1.8.3.4
Re: [PATCH 10/16] drm/gem: implement mmap access management
Quoted 10 lines · David Herrmann
Implement automatic access management for mmap offsets for all GEM drivers. This prevents user-space applications from "guessing" GEM BO offsets and accessing buffers which they don't own.
TTM drivers or other modesetting drivers with custom mm handling might make use of GEM but don't need its mmap helpers. To avoid unnecessary overhead, we limit GEM access management to drivers using
DRIVER_GEM_MMAP. So for TTM drivers GEM will not call any*_allow()or*_revoke()helpers.Signed-off-by David Herrmann <[email protected]>
Overall I'm not sold why we need the GEM_MMAP feature flag. Drivers that don't use drm_gem_mmap shouldn't get hurt with it if we ignore the little bit of useless overhead due to obj->vma_node. But they already have that anyway with obj->vma, so meh. And more incentives to move ttm over to the gem object manager completely ;-)
One comment below.
Cheers, Daniel
Quoted 52 lines
--- Documentation/DocBook/drm.tmpl | 13 +++++++++++++ drivers/gpu/drm/drm_gem.c | 36 ++++++++++++++++++++++++++++++++---- include/drm/drmP.h | 1 + 3 files changed, 46 insertions(+), 4 deletions(-)Documentation/DocBook/drm.tmpl +13
-0@@ -223,6 +223,19 @@ </para></listitem> </varlistentry> <varlistentry> + <term>DRIVER_GEM_MMAP</term> + <listitem><para> + Driver uses default GEM mmap helpers. This flag guarantees that + GEM core takes care of buffer access management and prevents + unprivileged users from mapping random buffers. This flag should + only be set by GEM-only drivers that use the drm_gem_mmap_*() + helpers directly. TTM, on the other hand, takes care of access + management itself, even though drivers might use DRIVER_GEM and + TTM at the same time. See the DRM VMA Offset Manager interface for + more information on buffer mmap() access management. + </para></listitem> + </varlistentry> + <varlistentry> <term>DRIVER_MODESET</term> <listitem><para> Driver supports mode setting interfaces (KMS).drivers/gpu/drm/drm_gem.c +7
-0@@ -236,6 +236,9 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)drm_gem_remove_prime_handles (obj, filp); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, filp->filp); +if (dev->driver->gem_close_object) dev->driver->gem_close_object (obj, filp);drm_gem_object_handle_unreference_unlocked (obj);@@ -288,15 +291,26 @@ drm_gem_handle_create(struct drm_file *file_priv,drm_gem_object_handle_reference (obj); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) { + ret =drm_vma_node_allow (&obj->vma_node, file_priv->filp); +if (ret) + goto err_handle;
drivers/gpu/drm/drm_gem.c drm_gem_handle_create(struct drm_file *file_priv, · line 303
Quoted 10 lines
drivers/gpu/drm/drm_gem.c +4
-4+ } +if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object (obj, file_priv); -if (ret) { -drm_gem_handle_delete (file_priv, *handlep); -return ret; - } +if (ret) + goto err_node;
The error handling cleanup changes here aren't required since handle_delete will dtrt anyway. Or at least I hope it does ;-) -Daniel
Quoted 74 lines
drivers/gpu/drm/drm_gem.c +21
-0}return 0 ; + +err_node: +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, file_priv->filp); +err_handle: +drm_gem_handle_delete (file_priv, *handlep); +return ret; }EXPORT_SYMBOL (drm_gem_handle_create);@@ -486,6 +500,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)drm_gem_remove_prime_handles (obj, file_priv); +if (drm_core_check_feature (dev,DRIVER_GEM_MMAP )) +drm_vma_node_revoke (&obj->vma_node, file_priv->filp); +if (dev->driver->gem_close_object) dev->driver->gem_close_object (obj, file_priv);@@ -610,6 +627,10 @@ EXPORT_SYMBOL(drm_gem_vm_close);* the GEM object is not looked up based on its fake offset. To implement the * DRM mmap operation, drivers should use the drm_gem_mmap() function. * +* drm_gem_mmap_obj() assumes the user is granted access to the buffer while +* drm_gem_mmap() prevents unprivileged users from mapping random objects. So +* callers must verify access restrictions before calling this helper. +* * NOTE: This function has to be protected with dev->struct_mutex * * Return 0 or success or -EINVAL if the object size is smaller than the VMA @@ -658,6 +679,9 @@ EXPORT_SYMBOL(drm_gem_mmap_obj);* Look up the GEM object based on the offset passed in (vma->vm_pgoff will * contain the fake offset we created when the GTT map ioctl was called on * the object) and map it with a call to drm_gem_mmap_obj(). +* +* If the caller is not granted access to the buffer object, the mmap will fail +* with EACCES. Please see DRIVER_GEM_MMAP for more information. */ int drm_gem_mmap (struct file *filp,struct vm_area_struct *vma) {@@ -678,6 +702,10 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)if (!node) {mutex_unlock (&dev->struct_mutex);return drm_mmap (filp, vma); + }else if (drm_core_check_feature (dev,DRIVER_GEM_MMAP ) && + !drm_vma_node_is_allowed (node, filp)) { +mutex_unlock (&dev->struct_mutex); +return -EACCES ; } obj = container_of(node, struct drm_gem_object, vma_node);include/drm/drmP.h +1
-0@@ -152,6 +152,7 @@ int drm_err(const char *func, const char *format, ...);#define DRIVER_GEM 0x1000#define DRIVER_MODESET 0x2000#define DRIVER_PRIME 0x4000 +#define DRIVER_GEM_MMAP 0x8000#define DRIVER_BUS_PCI 0x1#define DRIVER_BUS_PLATFORM 0x2Signature · 6 lines
1.8.3.4 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 10/16] drm/gem: implement mmap access management
Hi
Quoted 12 lines · Daniel Vetter
Quoted 10 lines · David Herrmann
Implement automatic access management for mmap offsets for all GEM drivers. This prevents user-space applications from "guessing" GEM BO offsets and accessing buffers which they don't own.
TTM drivers or other modesetting drivers with custom mm handling might make use of GEM but don't need its mmap helpers. To avoid unnecessary overhead, we limit GEM access management to drivers using
DRIVER_GEM_MMAP. So for TTM drivers GEM will not call any*_allow()or*_revoke()helpers.Signed-off-by David Herrmann <[email protected]>
Quoted 7 lines
Overall I'm not sold why we need the
GEM_MMAPfeature flag. Drivers that don't usedrm_gem_mmapshouldn't get hurt with it if we ignore the little bit of useless overhead due toobj->vma_node. But they already have that anyway withobj->vma, so meh. And more incentives to move ttm over to the gem object manager completely ;-)One comment below.
I fixed both, the error-path and GEM_MMAP. Thanks!
Cheers
David
PATCH 11/16 drm/i915: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/drm/i915/i915_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_drv.c +2 -1
@@ -1008,7 +1008,8 @@ static struct drm_driver driver = {*/ .driver_features =DRIVER_USE_AGP |DRIVER_REQUIRE_AGP |/* DRIVER_USE_MTRR |*/ - DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME, +DRIVER_HAVE_IRQ |DRIVER_IRQ_SHARED |DRIVER_GEM |DRIVER_PRIME | + DRIVER_GEM_MMAP, .load = i915_driver_load, .unload = i915_driver_unload, .open = i915_driver_open,
Signature · 1 line
1.8.3.4
PATCH 12/16 drm/exynos: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/exynos/exynos_drm_drv.c +2 -1
@@ -256,7 +256,8 @@ static const struct file_operations exynos_drm_driver_fops = {static struct drm_driver exynos_drm_driver = { .driver_features =DRIVER_HAVE_IRQ |DRIVER_MODESET | -DRIVER_GEM |DRIVER_PRIME , +DRIVER_GEM |DRIVER_PRIME | +DRIVER_GEM_MMAP , .load = exynos_drm_load, .unload = exynos_drm_unload, .open = exynos_drm_open,
Signature · 1 line
1.8.3.4
PATCH 13/16 drm/gma500: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/drm/gma500/psb_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/gma500/psb_drv.c +2 -1
@@ -628,7 +628,8 @@ static const struct file_operations psb_gem_fops = {static struct drm_driver driver = { .driver_features =DRIVER_HAVE_IRQ |DRIVER_IRQ_SHARED | \ -DRIVER_IRQ_VBL |DRIVER_MODESET |DRIVER_GEM , +DRIVER_IRQ_VBL |DRIVER_MODESET |DRIVER_GEM | +DRIVER_GEM_MMAP , .load = psb_driver_load, .unload = psb_driver_unload,
Signature · 1 line
1.8.3.4
PATCH 14/16 drm/omap: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/drm/omapdrm/omap_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/omapdrm/omap_drv.c +2 -1
@@ -605,7 +605,8 @@ static const struct file_operations omapdriver_fops = {static struct drm_driver omap_drm_driver = { .driver_features = -DRIVER_HAVE_IRQ |DRIVER_MODESET |DRIVER_GEM |DRIVER_PRIME , +DRIVER_HAVE_IRQ |DRIVER_MODESET |DRIVER_GEM | +DRIVER_PRIME |DRIVER_GEM_MMAP , .load = dev_load, .unload = dev_unload, .open = dev_open,
Signature · 1 line
1.8.3.4
Re: [PATCH 14/16] drm/omap: enable GEM mmap access management
Quoted 5 lines · David Herrmann
Set
DRIVER_GEM_MMAPto make GEM core track buffer accesses via the DRM VMA Offset Manager.Cc Rob Clark <[email protected]>Signed-off-by David Herrmann <[email protected]>
Quoted 21 lines
--- drivers/gpu/drm/omapdrm/omap_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/gpu/drm/omapdrm/omap_drv.c +2
-2@@ -605,7 +605,8 @@ static const struct file_operations omapdriver_fops = {static struct drm_driver omap_drm_driver = { .driver_features = -DRIVER_HAVE_IRQ |DRIVER_MODESET |DRIVER_GEM |DRIVER_PRIME , +DRIVER_HAVE_IRQ |DRIVER_MODESET |DRIVER_GEM | +DRIVER_PRIME |DRIVER_GEM_MMAP , .load = dev_load, .unload = dev_unload, .open = dev_open, --1.8.3.4
PATCH 15/16 drm/udl: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/drm/udl/udl_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/udl/udl_drv.c +2 -1
@@ -73,7 +73,8 @@ static const struct file_operations udl_driver_fops = { };static struct drm_driver driver = { - .driver_features =DRIVER_MODESET |DRIVER_GEM |DRIVER_PRIME , + .driver_features =DRIVER_MODESET |DRIVER_GEM |DRIVER_PRIME | +DRIVER_GEM_MMAP , .load = udl_driver_load, .unload = udl_driver_unload,
Signature · 1 line
1.8.3.4
PATCH 16/16 drm/host1x: enable GEM mmap access management
In reply to David HerrmannSet DRIVER_GEM_MMAP to make GEM core track buffer accesses via the DRM VMA Offset Manager.
--- drivers/gpu/host1x/drm/drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/host1x/drm/drm.c +1 -1
@@ -613,7 +613,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)#endif struct drm_driver tegra_drm_driver = { - .driver_features =DRIVER_MODESET |DRIVER_GEM , + .driver_features =DRIVER_MODESET |DRIVER_GEM |DRIVER_GEM_MMAP , .load = tegra_drm_load, .unload = tegra_drm_unload, .open = tegra_drm_open,
Signature · 6 lines
1.8.3.4 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel