Skip to content

Commit 933db73

Browse files
vaverinkraxel
authored andcommitted
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: [email protected] Fixes: f64122c ("drm: add new QXL driver. (v1.4)") Signed-off-by: Vasily Averin <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Gerd Hoffmann <[email protected]>
1 parent 5b5703d commit 933db73

File tree

4 files changed

+7
-11
lines changed

4 files changed

+7
-11
lines changed

drivers/gpu/drm/qxl/qxl_cmd.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,8 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
500500
/* no need to add a release to the fence for this surface bo,
501501
since it is only released when we ask to destroy the surface
502502
and it would never signal otherwise */
503-
qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
504503
qxl_release_fence_buffer_objects(release);
504+
qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
505505

506506
surf->hw_surf_alloc = true;
507507
spin_lock(&qdev->surf_id_idr_lock);
@@ -543,9 +543,8 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
543543
cmd->surface_id = id;
544544
qxl_release_unmap(qdev, release, &cmd->release_info);
545545

546-
qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
547-
548546
qxl_release_fence_buffer_objects(release);
547+
qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
549548

550549
return 0;
551550
}

drivers/gpu/drm/qxl/qxl_display.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
510510
cmd->u.set.visible = 1;
511511
qxl_release_unmap(qdev, release, &cmd->release_info);
512512

513-
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
514513
qxl_release_fence_buffer_objects(release);
514+
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
515515

516516
return ret;
517517

@@ -652,8 +652,8 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
652652
cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
653653

654654
qxl_release_unmap(qdev, release, &cmd->release_info);
655-
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
656655
qxl_release_fence_buffer_objects(release);
656+
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
657657

658658
if (old_cursor_bo != NULL)
659659
qxl_bo_unpin(old_cursor_bo);
@@ -700,8 +700,8 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
700700
cmd->type = QXL_CURSOR_HIDE;
701701
qxl_release_unmap(qdev, release, &cmd->release_info);
702702

703-
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
704703
qxl_release_fence_buffer_objects(release);
704+
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
705705
}
706706

707707
static void qxl_update_dumb_head(struct qxl_device *qdev,

drivers/gpu/drm/qxl/qxl_draw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
243243
}
244244
qxl_bo_kunmap(clips_bo);
245245

246-
qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
247246
qxl_release_fence_buffer_objects(release);
247+
qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
248248

249249
out_release_backoff:
250250
if (ret)

drivers/gpu/drm/qxl/qxl_ioctl.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
261261
apply_surf_reloc(qdev, &reloc_info[i]);
262262
}
263263

264+
qxl_release_fence_buffer_objects(release);
264265
ret = qxl_push_command_ring_release(qdev, release, cmd->type, true);
265-
if (ret)
266-
qxl_release_backoff_reserve_list(release);
267-
else
268-
qxl_release_fence_buffer_objects(release);
269266

270267
out_free_bos:
271268
out_free_release:

0 commit comments

Comments
 (0)