From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Herrmann Subject: [PATCH 2/7] drm/gem: implement vma access management Date: Sun, 25 Aug 2013 18:28:58 +0200 Message-ID: <1377448143-746-2-git-send-email-dh.herrmann@gmail.com> References: <1377256408-746-1-git-send-email-dh.herrmann@gmail.com> <1377448143-746-1-git-send-email-dh.herrmann@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail-ee0-f54.google.com (mail-ee0-f54.google.com [74.125.83.54]) by gabe.freedesktop.org (Postfix) with ESMTP id 8ED6CE5EC1 for ; Sun, 25 Aug 2013 09:29:41 -0700 (PDT) Received: by mail-ee0-f54.google.com with SMTP id e53so1155891eek.41 for ; Sun, 25 Aug 2013 09:29:40 -0700 (PDT) In-Reply-To: <1377448143-746-1-git-send-email-dh.herrmann@gmail.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org To: dri-devel@lists.freedesktop.org Cc: Dave Airlie List-Id: dri-devel@lists.freedesktop.org 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 --- drivers/gpu/drm/drm_gem.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d6122ae..b2d59b2 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) spin_unlock(&filp->table_lock); drm_gem_remove_prime_handles(obj, filp); + drm_vma_node_revoke(&obj->vma_node, filp->filp); if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, filp); @@ -357,6 +358,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv, } *handlep = ret; + ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); + if (ret) { + drm_gem_handle_delete(file_priv, *handlep); + return ret; + } if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object(obj, file_priv); @@ -701,6 +707,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) struct drm_device *dev = obj->dev; drm_gem_remove_prime_handles(obj, file_priv); + drm_vma_node_revoke(&obj->vma_node, file_priv->filp); if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); @@ -793,6 +800,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 @@ -841,6 +852,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 the vma manager for more information. */ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -861,6 +875,9 @@ 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_vma_node_is_allowed(node, filp)) { + mutex_unlock(&dev->struct_mutex); + return -EACCES; } obj = container_of(node, struct drm_gem_object, vma_node); -- 1.8.4