diff options
| author | Vasily Averin <vvs@virtuozzo.com> | 2020-04-29 12:01:24 +0300 |
|---|---|---|
| committer | Gerd Hoffmann <kraxel@redhat.com> | 2020-04-29 14:21:34 +0300 |
| commit | 933db73351d359f74b14f4af095808260aff11f9 (patch) | |
| tree | 1fe36df154fb79400c27cd3c02a22922348788dc /drivers/gpu/drm/qxl/qxl_cmd.c | |
| parent | 5b5703dbafae74adfbe298a56a81694172caf5e6 (diff) | |
| download | linux-933db73351d359f74b14f4af095808260aff11f9.tar.xz | |
drm/qxl: qxl_release use after free
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>
Diffstat (limited to 'drivers/gpu/drm/qxl/qxl_cmd.c')
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_cmd.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index fa8762d15d0f..05863b253d68 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -500,8 +500,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); @@ -543,9 +543,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; } |
