apply_reloc() and apply_surf_reloc() map a single page via
qxl_bo_kmap_atomic_page() and then write 8 or 4 bytes at the
page-relative offset (dst_offset & ~PAGE_MASK). When the offset is
near the end of the page the write extends past the mapped region into
adjacent kernel virtual address space.
For example, a BO relocation at page offset 4092 writes bytes 4092-4099,
crossing the 4096-byte page boundary. The fixmap slot only covers one
page, so bytes 4096-4099 corrupt whatever virtual page follows in the
kernel's fixmap area.
Reject any relocation whose page-relative offset plus write width
exceeds PAGE_SIZE.
Fixes: f64122c1f6ad ("drm: add qxl driver.")
Cc: [email protected]
Signed-off-by: Aldo Ariel Panzardo <[email protected]>
---
drivers/gpu/drm/qxl/qxl_ioctl.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
index e727a35c9..9fba6e26d 100644
--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -247,6 +247,12 @@ static int qxl_process_single_command(struct qxl_device
*qdev,
goto out_free_bos;
}
+ if ((reloc_info[i].dst_offset & ~PAGE_MASK) + write_size >
+ PAGE_SIZE) {
+ ret = -EINVAL;
+ goto out_free_bos;
+ }
+
/* reserve and validate the reloc dst bo */
if (reloc.reloc_type == QXL_RELOC_TYPE_BO || reloc.src_handle) {
ret = qxlhw_handle_to_bo(file_priv, reloc.src_handle,
release,
--
2.43.0