mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
drm/qxl: qxl_release use after free
commit933db73351upstream. 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:f64122c1f6("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 v.4.19 stable] Signed-off-by: Vasily Averin <vvs@virtuozzo.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a8d36f64dd
commit
0d28ac49eb
@@ -501,8 +501,8 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
|
||||
/* 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);
|
||||
@@ -544,9 +544,8 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -532,8 +532,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
|
||||
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;
|
||||
|
||||
@@ -694,8 +694,8 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
|
||||
cmd->u.position.y = plane->state->crtc_y + fb->hot_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);
|
||||
|
||||
if (old_cursor_bo)
|
||||
qxl_bo_unref(&old_cursor_bo);
|
||||
@@ -740,8 +740,8 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
|
||||
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);
|
||||
}
|
||||
|
||||
static int qxl_plane_prepare_fb(struct drm_plane *plane,
|
||||
|
||||
@@ -241,8 +241,8 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
|
||||
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 *qdev,
|
||||
}
|
||||
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 *qdev,
|
||||
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_draw_fill_rec)
|
||||
|
||||
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)
|
||||
|
||||
@@ -257,11 +257,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user