APPLIED: [SRU Bionic 1/1] UBUNTU: SAUCE: drm/vmwgfx: Fix stale file descriptors on failed usercopy
Luke Nowakowski-Krijger
luke.nowakowskikrijger at canonical.com
Thu Jan 27 22:33:09 UTC 2022
On Thu, Jan 27, 2022 at 12:59 PM Thadeu Lima de Souza Cascardo <
cascardo at canonical.com> wrote:
> From: Mathias Krause <minipli at grsecurity.net>
>
> A failing usercopy of the fence_rep object will lead to a stale entry in
> the file descriptor table as put_unused_fd() won't release it. This
> enables userland to refer to a dangling 'file' object through that still
> valid file descriptor, leading to all kinds of use-after-free
> exploitation scenarios.
>
> Fix this by deferring the call to fd_install() until after the usercopy
> has succeeded.
>
> Cc: Zack Rusin <zackr at vmware.com>
> Fixes: c906965dee22 ("drm/vmwgfx: Add export fence to file descriptor
> support")
> [mks: backport to v4.19 and older]
> Signed-off-by: Mathias Krause <minipli at grsecurity.net>
> CVE-2022-22942
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at canonical.com>
> ---
> drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 ++--
> drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 34 ++++++++++++-------------
> drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 2 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +-
> 4 files changed, 21 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> index 8c65cc3b0dda..8f5321f09856 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> @@ -837,15 +837,14 @@ extern int vmw_execbuf_fence_commands(struct
> drm_file *file_priv,
> struct vmw_private *dev_priv,
> struct vmw_fence_obj **p_fence,
> uint32_t *p_handle);
> -extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
> +extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
> struct vmw_fpriv *vmw_fp,
> int ret,
> struct drm_vmw_fence_rep __user
> *user_fence_rep,
> struct vmw_fence_obj *fence,
> uint32_t fence_handle,
> - int32_t out_fence_fd,
> - struct sync_file *sync_file);
> + int32_t out_fence_fd);
> extern int vmw_validate_single_buffer(struct vmw_private *dev_priv,
> struct ttm_buffer_object *bo,
> bool interruptible,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> index dc677ba4dc38..996696ad6f98 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> @@ -3848,20 +3848,19 @@ int vmw_execbuf_fence_commands(struct drm_file
> *file_priv,
> * object so we wait for it immediately, and then unreference the
> * user-space reference.
> */
> -void
> +int
> vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
> struct vmw_fpriv *vmw_fp,
> int ret,
> struct drm_vmw_fence_rep __user
> *user_fence_rep,
> struct vmw_fence_obj *fence,
> uint32_t fence_handle,
> - int32_t out_fence_fd,
> - struct sync_file *sync_file)
> + int32_t out_fence_fd)
> {
> struct drm_vmw_fence_rep fence_rep;
>
> if (user_fence_rep == NULL)
> - return;
> + return 0;
>
> memset(&fence_rep, 0, sizeof(fence_rep));
>
> @@ -3889,20 +3888,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private
> *dev_priv,
> * and unreference the handle.
> */
> if (unlikely(ret != 0) && (fence_rep.error == 0)) {
> - if (sync_file)
> - fput(sync_file->file);
> -
> - if (fence_rep.fd != -1) {
> - put_unused_fd(fence_rep.fd);
> - fence_rep.fd = -1;
> - }
> -
> ttm_ref_object_base_unref(vmw_fp->tfile,
> fence_handle, TTM_REF_USAGE);
> DRM_ERROR("Fence copy error. Syncing.\n");
> (void) vmw_fence_obj_wait(fence, false, false,
> VMW_FENCE_WAIT_TIMEOUT);
> }
> +
> + return ret ? -EFAULT : 0;
> }
>
> /**
> @@ -4262,16 +4255,23 @@ int vmw_execbuf_process(struct drm_file *file_priv,
>
> (void) vmw_fence_obj_wait(fence, false, false,
> VMW_FENCE_WAIT_TIMEOUT);
> + }
> + }
> +
> + ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
> ret,
> + user_fence_rep, fence, handle,
> out_fence_fd);
> +
> + if (sync_file) {
> + if (ret) {
> + /* usercopy of fence failed, put the file object */
> + fput(sync_file->file);
> + put_unused_fd(out_fence_fd);
> } else {
> /* Link the fence with the FD created earlier */
> fd_install(out_fence_fd, sync_file->file);
> }
> }
>
> - vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
> - user_fence_rep, fence, handle,
> - out_fence_fd, sync_file);
> -
> /* Don't unreference when handing fence out */
> if (unlikely(out_fence != NULL)) {
> *out_fence = fence;
> @@ -4290,7 +4290,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
> */
> vmw_resource_list_unreference(sw_context, &resource_list);
>
> - return 0;
> + return ret;
>
> out_unlock_binding:
> mutex_unlock(&dev_priv->binding_mutex);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> index 55214d0da66e..7c92d369d544 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> @@ -1151,7 +1151,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev,
> void *data,
> }
>
> vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep,
> fence,
> - handle, -1, NULL);
> + handle, -1);
> vmw_fence_obj_unreference(&fence);
> return 0;
> out_no_create:
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 406f8e82a4d6..f1abdb135c86 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -2511,7 +2511,7 @@ void vmw_kms_helper_buffer_finish(struct vmw_private
> *dev_priv,
> if (file_priv)
> vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
> ret, user_fence_rep, fence,
> - handle, -1, NULL);
> + handle, -1);
> if (out_fence)
> *out_fence = fence;
> else
> --
> 2.32.0
>
>
>
Applied to Bionic:linux/master-next.
Thanks :)
- Luke
> --
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20220127/92f2540b/attachment-0001.html>
More information about the kernel-team
mailing list