From: Greg Kroah-Hartman Date: Mon, 4 May 2020 16:41:56 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.4.222~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=144dd682ed5755a6c9cc85b98aa797f6d525d8e9;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: drm-qxl-qxl_release-use-after-free.patch --- 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 index 00000000000..86fda2b1306 --- /dev/null +++ b/queue-4.9/drm-qxl-qxl_release-use-after-free.patch @@ -0,0 +1,156 @@ +From 933db73351d359f74b14f4af095808260aff11f9 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 29 Apr 2020 12:01:24 +0300 +Subject: drm/qxl: qxl_release use after free + +From: Vasily Averin + +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 +Link: http://patchwork.freedesktop.org/patch/msgid/fa17b338-66ae-f299-68fe-8d32419d9071@virtuozzo.com +Signed-off-by: Gerd Hoffmann +[backported to v4.9-stable] +Signed-off-by: Vasily Averin +Signed-off-by: Greg Kroah-Hartman +--- + 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: diff --git a/queue-4.9/series b/queue-4.9/series index 531a77d79ed..a36e7bb0b88 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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