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

Reply via email to