Blame SOURCES/CVE-2022-22942.patch

ec80f5
From 73c1db23af5c7364af380d21739a6e1220a2490d Mon Sep 17 00:00:00 2001
ec80f5
From: Joe Lawrence <joe.lawrence@redhat.com>
ec80f5
Date: Tue, 1 Mar 2022 15:34:07 -0500
ec80f5
Subject: [KPATCH CVE-2022-22942] drm/vmwgfx: kpatch fixes for CVE-2022-22942
ec80f5
ec80f5
Kernels:
ec80f5
4.18.0-348.el8
ec80f5
4.18.0-348.2.1.el8_5
ec80f5
4.18.0-348.7.1.el8_5
ec80f5
4.18.0-348.12.2.el8_5
ec80f5
ec80f5
Changes since last build:
ec80f5
arches: x86_64
ec80f5
vmwgfx_execbuf.o: changed function: vmw_execbuf_copy_fence_user
ec80f5
vmwgfx_execbuf.o: changed function: vmw_execbuf_process
ec80f5
vmwgfx_fence.o: changed function: vmw_fence_event_ioctl
ec80f5
vmwgfx_kms.o: changed function: vmw_kms_helper_validation_finish
ec80f5
---------------------------
ec80f5
ec80f5
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-8/-/merge_requests/32
ec80f5
Approved-by: Yannick Cote (@ycote1)
ec80f5
Kernels:
ec80f5
4.18.0-348.el8
ec80f5
4.18.0-348.2.1.el8_5
ec80f5
4.18.0-348.7.1.el8_5
ec80f5
4.18.0-348.12.2.el8_5
ec80f5
ec80f5
Modifications: none
ec80f5
ec80f5
commit 1b221c65601c93cb4ad2b24487c0015d6bae7c7f
ec80f5
Author: Dave Airlie <airlied@redhat.com>
ec80f5
Date:   Fri Jan 28 16:36:48 2022 -0500
ec80f5
ec80f5
    drm/vmwgfx: Fix stale file descriptors on failed usercopy
ec80f5
ec80f5
    Bugzilla: https://bugzilla.redhat.com/2047601
ec80f5
    CVE: CVE-2022-22942
ec80f5
    Y-Commit: b6793b842fba127aa491384431e84b79c7619afd
ec80f5
ec80f5
    O-Bugzilla: http://bugzilla.redhat.com/2047602
ec80f5
    O-CVE: CVE-2022-22942
ec80f5
ec80f5
    commit a0f90c8815706981c483a652a6aefca51a5e191c
ec80f5
    Author: Mathias Krause <minipli@grsecurity.net>
ec80f5
    Date:   Thu Jan 27 18:34:19 2022 +1000
ec80f5
ec80f5
        drm/vmwgfx: Fix stale file descriptors on failed usercopy
ec80f5
ec80f5
        A failing usercopy of the fence_rep object will lead to a stale entry in
ec80f5
        the file descriptor table as put_unused_fd() won't release it. This
ec80f5
        enables userland to refer to a dangling 'file' object through that still
ec80f5
        valid file descriptor, leading to all kinds of use-after-free
ec80f5
        exploitation scenarios.
ec80f5
ec80f5
        Fix this by deferring the call to fd_install() until after the usercopy
ec80f5
        has succeeded.
ec80f5
ec80f5
        Fixes: c906965dee22 ("drm/vmwgfx: Add export fence to file descriptor support")
ec80f5
        Signed-off-by: Mathias Krause <minipli@grsecurity.net>
ec80f5
        Signed-off-by: Zack Rusin <zackr@vmware.com>
ec80f5
        Signed-off-by: Dave Airlie <airlied@redhat.com>
ec80f5
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
ec80f5
ec80f5
    Signed-off-by: Dave Airlie <airlied@redhat.com>
ec80f5
    Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
ec80f5
ec80f5
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
ec80f5
---
ec80f5
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h     |  5 ++--
ec80f5
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 33 +++++++++++++------------
ec80f5
 drivers/gpu/drm/vmwgfx/vmwgfx_fence.c   |  2 +-
ec80f5
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c     |  2 +-
ec80f5
 4 files changed, 21 insertions(+), 21 deletions(-)
ec80f5
ec80f5
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
ec80f5
index eb76a6b9ebca..2f4f39446240 100644
ec80f5
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
ec80f5
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
ec80f5
@@ -1069,15 +1069,14 @@ extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
ec80f5
 				      struct vmw_private *dev_priv,
ec80f5
 				      struct vmw_fence_obj **p_fence,
ec80f5
 				      uint32_t *p_handle);
ec80f5
-extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
ec80f5
+extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
ec80f5
 					struct vmw_fpriv *vmw_fp,
ec80f5
 					int ret,
ec80f5
 					struct drm_vmw_fence_rep __user
ec80f5
 					*user_fence_rep,
ec80f5
 					struct vmw_fence_obj *fence,
ec80f5
 					uint32_t fence_handle,
ec80f5
-					int32_t out_fence_fd,
ec80f5
-					struct sync_file *sync_file);
ec80f5
+					int32_t out_fence_fd);
ec80f5
 bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
ec80f5
 
ec80f5
 /**
ec80f5
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
ec80f5
index 462f17320708..399cb4cce292 100644
ec80f5
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
ec80f5
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
ec80f5
@@ -3804,17 +3804,17 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
ec80f5
  * Also if copying fails, user-space will be unable to signal the fence object
ec80f5
  * so we wait for it immediately, and then unreference the user-space reference.
ec80f5
  */
ec80f5
-void
ec80f5
+int
ec80f5
 vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
ec80f5
 			    struct vmw_fpriv *vmw_fp, int ret,
ec80f5
 			    struct drm_vmw_fence_rep __user *user_fence_rep,
ec80f5
 			    struct vmw_fence_obj *fence, uint32_t fence_handle,
ec80f5
-			    int32_t out_fence_fd, struct sync_file *sync_file)
ec80f5
+			    int32_t out_fence_fd)
ec80f5
 {
ec80f5
 	struct drm_vmw_fence_rep fence_rep;
ec80f5
 
ec80f5
 	if (user_fence_rep == NULL)
ec80f5
-		return;
ec80f5
+		return 0;
ec80f5
 
ec80f5
 	memset(&fence_rep, 0, sizeof(fence_rep));
ec80f5
 
ec80f5
@@ -3842,20 +3842,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
ec80f5
 	 * handle.
ec80f5
 	 */
ec80f5
 	if (unlikely(ret != 0) && (fence_rep.error == 0)) {
ec80f5
-		if (sync_file)
ec80f5
-			fput(sync_file->file);
ec80f5
-
ec80f5
-		if (fence_rep.fd != -1) {
ec80f5
-			put_unused_fd(fence_rep.fd);
ec80f5
-			fence_rep.fd = -1;
ec80f5
-		}
ec80f5
-
ec80f5
 		ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle,
ec80f5
 					  TTM_REF_USAGE);
ec80f5
 		VMW_DEBUG_USER("Fence copy error. Syncing.\n");
ec80f5
 		(void) vmw_fence_obj_wait(fence, false, false,
ec80f5
 					  VMW_FENCE_WAIT_TIMEOUT);
ec80f5
 	}
ec80f5
+
ec80f5
+	return ret ? -EFAULT : 0;
ec80f5
 }
ec80f5
 
ec80f5
 /**
ec80f5
@@ -4193,16 +4187,23 @@ int vmw_execbuf_process(struct drm_file *file_priv,
ec80f5
 
ec80f5
 			(void) vmw_fence_obj_wait(fence, false, false,
ec80f5
 						  VMW_FENCE_WAIT_TIMEOUT);
ec80f5
+		}
ec80f5
+	}
ec80f5
+
ec80f5
+	ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
ec80f5
+				    user_fence_rep, fence, handle, out_fence_fd);
ec80f5
+
ec80f5
+	if (sync_file) {
ec80f5
+		if (ret) {
ec80f5
+			/* usercopy of fence failed, put the file object */
ec80f5
+			fput(sync_file->file);
ec80f5
+			put_unused_fd(out_fence_fd);
ec80f5
 		} else {
ec80f5
 			/* Link the fence with the FD created earlier */
ec80f5
 			fd_install(out_fence_fd, sync_file->file);
ec80f5
 		}
ec80f5
 	}
ec80f5
 
ec80f5
-	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
ec80f5
-				    user_fence_rep, fence, handle, out_fence_fd,
ec80f5
-				    sync_file);
ec80f5
-
ec80f5
 	/* Don't unreference when handing fence out */
ec80f5
 	if (unlikely(out_fence != NULL)) {
ec80f5
 		*out_fence = fence;
ec80f5
@@ -4220,7 +4221,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
ec80f5
 	 */
ec80f5
 	vmw_validation_unref_lists(&val_ctx);
ec80f5
 
ec80f5
-	return 0;
ec80f5
+	return ret;
ec80f5
 
ec80f5
 out_unlock_binding:
ec80f5
 	mutex_unlock(&dev_priv->binding_mutex);
ec80f5
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
ec80f5
index 378ec7600154..23cf8a264f3d 100644
ec80f5
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
ec80f5
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
ec80f5
@@ -1167,7 +1167,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
ec80f5
 	}
ec80f5
 
ec80f5
 	vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
ec80f5
-				    handle, -1, NULL);
ec80f5
+				    handle, -1);
ec80f5
 	vmw_fence_obj_unreference(&fence);
ec80f5
 	return 0;
ec80f5
 out_no_create:
ec80f5
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
ec80f5
index 9a89f658e501..bb0448044ced 100644
ec80f5
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
ec80f5
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
ec80f5
@@ -2477,7 +2477,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
ec80f5
 	if (file_priv)
ec80f5
 		vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
ec80f5
 					    ret, user_fence_rep, fence,
ec80f5
-					    handle, -1, NULL);
ec80f5
+					    handle, -1);
ec80f5
 	if (out_fence)
ec80f5
 		*out_fence = fence;
ec80f5
 	else
ec80f5
-- 
ec80f5
2.34.1
ec80f5
ec80f5