]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 May 2020 16:41:56 +0000 (18:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 May 2020 16:41:56 +0000 (18:41 +0200)
added patches:
drm-qxl-qxl_release-use-after-free.patch

queue-4.9/drm-qxl-qxl_release-use-after-free.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/drm-qxl-qxl_release-use-after-free.patch b/queue-4.9/drm-qxl-qxl_release-use-after-free.patch
new file mode 100644 (file)
index 0000000..86fda2b
--- /dev/null
@@ -0,0 +1,156 @@
+From 933db73351d359f74b14f4af095808260aff11f9 Mon Sep 17 00:00:00 2001
+From: Vasily Averin <vvs@virtuozzo.com>
+Date: Wed, 29 Apr 2020 12:01:24 +0300
+Subject: drm/qxl: qxl_release use after free
+
+From: Vasily Averin <vvs@virtuozzo.com>
+
+commit 933db73351d359f74b14f4af095808260aff11f9 upstream.
+
+qxl_release should not be accesses after qxl_push_*_ring_release() calls:
+userspace driver can process submitted command quickly, move qxl_release
+into release_ring, generate interrupt and trigger garbage collector.
+
+It can lead to crashes in qxl driver or trigger memory corruption
+in some kmalloc-192 slab object
+
+Gerd Hoffmann proposes to swap the qxl_release_fence_buffer_objects() +
+qxl_push_{cursor,command}_ring_release() calls to close that race window.
+
+cc: stable@vger.kernel.org
+Fixes: f64122c1f6ad ("drm: add new QXL driver. (v1.4)")
+Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/fa17b338-66ae-f299-68fe-8d32419d9071@virtuozzo.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+[backported to v4.9-stable]
+Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/qxl/qxl_cmd.c     |    5 ++---
+ drivers/gpu/drm/qxl/qxl_display.c |    8 ++++----
+ drivers/gpu/drm/qxl/qxl_draw.c    |    8 ++++----
+ drivers/gpu/drm/qxl/qxl_ioctl.c   |    5 +----
+ 4 files changed, 11 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/qxl/qxl_cmd.c
++++ b/drivers/gpu/drm/qxl/qxl_cmd.c
+@@ -529,8 +529,8 @@ int qxl_hw_surface_alloc(struct qxl_devi
+       /* no need to add a release to the fence for this surface bo,
+          since it is only released when we ask to destroy the surface
+          and it would never signal otherwise */
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
+       surf->hw_surf_alloc = true;
+       spin_lock(&qdev->surf_id_idr_lock);
+@@ -572,9 +572,8 @@ int qxl_hw_surface_dealloc(struct qxl_de
+       cmd->surface_id = id;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
+-
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
+       return 0;
+ }
+--- a/drivers/gpu/drm/qxl/qxl_display.c
++++ b/drivers/gpu/drm/qxl/qxl_display.c
+@@ -292,8 +292,8 @@ qxl_hide_cursor(struct qxl_device *qdev)
+       cmd->type = QXL_CURSOR_HIDE;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+-      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       return 0;
+ }
+@@ -333,8 +333,8 @@ static int qxl_crtc_apply_cursor(struct
+       cmd->u.set.visible = 1;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+-      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       return ret;
+@@ -436,8 +436,8 @@ static int qxl_crtc_cursor_set2(struct d
+       cmd->u.set.visible = 1;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+-      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       /* finish with the userspace bo */
+       ret = qxl_bo_reserve(user_bo, false);
+@@ -497,8 +497,8 @@ static int qxl_crtc_cursor_move(struct d
+       cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+-      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       return 0;
+ }
+--- a/drivers/gpu/drm/qxl/qxl_draw.c
++++ b/drivers/gpu/drm/qxl/qxl_draw.c
+@@ -241,8 +241,8 @@ void qxl_draw_opaque_fb(const struct qxl
+               qxl_bo_physical_address(qdev, dimage->bo, 0);
+       qxl_release_unmap(qdev, release, &drawable->release_info);
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+ out_free_palette:
+       if (palette_bo)
+@@ -382,8 +382,8 @@ void qxl_draw_dirty_fb(struct qxl_device
+       }
+       qxl_bo_kunmap(clips_bo);
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+ out_release_backoff:
+       if (ret)
+@@ -433,8 +433,8 @@ void qxl_draw_copyarea(struct qxl_device
+       drawable->u.copy_bits.src_pos.y = sy;
+       qxl_release_unmap(qdev, release, &drawable->release_info);
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+ out_free_release:
+       if (ret)
+@@ -477,8 +477,8 @@ void qxl_draw_fill(struct qxl_draw_fill
+       qxl_release_unmap(qdev, release, &drawable->release_info);
+-      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+       qxl_release_fence_buffer_objects(release);
++      qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
+ out_free_release:
+       if (ret)
+--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
+@@ -256,11 +256,8 @@ static int qxl_process_single_command(st
+                       apply_surf_reloc(qdev, &reloc_info[i]);
+       }
++      qxl_release_fence_buffer_objects(release);
+       ret = qxl_push_command_ring_release(qdev, release, cmd->type, true);
+-      if (ret)
+-              qxl_release_backoff_reserve_list(release);
+-      else
+-              qxl_release_fence_buffer_objects(release);
+ out_free_bos:
+ out_free_release:
index 531a77d79ed445a165bbac8404fa1616fc3c79e3..a36e7bb0b8871a8fcd21803b28a4a7b0ed3d48c3 100644 (file)
@@ -15,3 +15,4 @@ alsa-opti9xx-shut-up-gcc-10-range-warning.patch
 nfs-fix-potential-posix_acl-refcnt-leak-in-nfs3_set_acl.patch
 dmaengine-dmatest-fix-iteration-non-stop-logic.patch
 selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch
+drm-qxl-qxl_release-use-after-free.patch