aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_gem.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-08-25 12:28:58 -0400
committerDave Airlie <airlied@redhat.com>2013-08-26 21:54:56 -0400
commitca481c9b2a3ae3598453535b8f0369f1f875d52f (patch)
tree31b84f86251db898aa8fc8a1dfa14c3bd9a0ae97 /drivers/gpu/drm/drm_gem.c
parent88d7ebe59341dc3b82e662b80809694e3c6b3766 (diff)
drm/gem: implement vma access management
We implement automatic vma mmap() access management for all drivers using gem_mmap. We use the vma manager to add each open-file that creates a gem-handle to the vma-node of the underlying gem object. Once the handle is destroyed, we drop the open-file again. This allows us to use drm_vma_node_is_allowed() on _any_ gem object to see whether an open-file is granted access. In drm_gem_mmap() we use this to verify that unprivileged users cannot guess gem offsets and map arbitrary buffers. Note that this manages access for _all_ gem users (also TTM+GEM), but the actual access checks are only done for drm_gem_mmap(). TTM drivers use the TTM mmap helpers, which need to do that separately. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r--drivers/gpu/drm/drm_gem.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index d6122ae6bf86..b2d59b2d3acc 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -298,6 +298,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
298 spin_unlock(&filp->table_lock); 298 spin_unlock(&filp->table_lock);
299 299
300 drm_gem_remove_prime_handles(obj, filp); 300 drm_gem_remove_prime_handles(obj, filp);
301 drm_vma_node_revoke(&obj->vma_node, filp->filp);
301 302
302 if (dev->driver->gem_close_object) 303 if (dev->driver->gem_close_object)
303 dev->driver->gem_close_object(obj, filp); 304 dev->driver->gem_close_object(obj, filp);
@@ -357,6 +358,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
357 } 358 }
358 *handlep = ret; 359 *handlep = ret;
359 360
361 ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
362 if (ret) {
363 drm_gem_handle_delete(file_priv, *handlep);
364 return ret;
365 }
360 366
361 if (dev->driver->gem_open_object) { 367 if (dev->driver->gem_open_object) {
362 ret = dev->driver->gem_open_object(obj, file_priv); 368 ret = dev->driver->gem_open_object(obj, file_priv);
@@ -701,6 +707,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
701 struct drm_device *dev = obj->dev; 707 struct drm_device *dev = obj->dev;
702 708
703 drm_gem_remove_prime_handles(obj, file_priv); 709 drm_gem_remove_prime_handles(obj, file_priv);
710 drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
704 711
705 if (dev->driver->gem_close_object) 712 if (dev->driver->gem_close_object)
706 dev->driver->gem_close_object(obj, file_priv); 713 dev->driver->gem_close_object(obj, file_priv);
@@ -793,6 +800,10 @@ EXPORT_SYMBOL(drm_gem_vm_close);
793 * the GEM object is not looked up based on its fake offset. To implement the 800 * the GEM object is not looked up based on its fake offset. To implement the
794 * DRM mmap operation, drivers should use the drm_gem_mmap() function. 801 * DRM mmap operation, drivers should use the drm_gem_mmap() function.
795 * 802 *
803 * drm_gem_mmap_obj() assumes the user is granted access to the buffer while
804 * drm_gem_mmap() prevents unprivileged users from mapping random objects. So
805 * callers must verify access restrictions before calling this helper.
806 *
796 * NOTE: This function has to be protected with dev->struct_mutex 807 * NOTE: This function has to be protected with dev->struct_mutex
797 * 808 *
798 * Return 0 or success or -EINVAL if the object size is smaller than the VMA 809 * Return 0 or success or -EINVAL if the object size is smaller than the VMA
@@ -841,6 +852,9 @@ EXPORT_SYMBOL(drm_gem_mmap_obj);
841 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will 852 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
842 * contain the fake offset we created when the GTT map ioctl was called on 853 * contain the fake offset we created when the GTT map ioctl was called on
843 * the object) and map it with a call to drm_gem_mmap_obj(). 854 * the object) and map it with a call to drm_gem_mmap_obj().
855 *
856 * If the caller is not granted access to the buffer object, the mmap will fail
857 * with EACCES. Please see the vma manager for more information.
844 */ 858 */
845int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) 859int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
846{ 860{
@@ -861,6 +875,9 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
861 if (!node) { 875 if (!node) {
862 mutex_unlock(&dev->struct_mutex); 876 mutex_unlock(&dev->struct_mutex);
863 return drm_mmap(filp, vma); 877 return drm_mmap(filp, vma);
878 } else if (!drm_vma_node_is_allowed(node, filp)) {
879 mutex_unlock(&dev->struct_mutex);
880 return -EACCES;
864 } 881 }
865 882
866 obj = container_of(node, struct drm_gem_object, vma_node); 883 obj = container_of(node, struct drm_gem_object, vma_node);