vmw_cmd_res_switch_backup lets userspace bind an arbitrary MOB to a
resource without checking that the MOB is large enough for the resource's
guest_memory_size. The dirty-tracking bitmap is allocated based on the
MOB size, but later accessed using the (larger) surface size, causing an
out-of-bounds write in the bitmap that corrupts adjacent slab memory.

Add a check that backup_offset + res->guest_memory_size does not exceed
the buffer size before allowing the backup switch.

Fixes: a97e21923b42 ("drm/vmwgfx: Hook up guest-backed surfaces")
Cc: [email protected]
Reported-by: Zero Day Initiative <[email protected]>
Reported-by: [email protected] # ZDI-CAN-34068
Closes: 
https://lore.kernel.org/all/byapr01mb38301cfc012e873340f77e3d80...@byapr01mb3830.prod.exchangelabs.com/
---
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index a9136a6523cb..0156aee84c9f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1718,6 +1718,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private 
*dev_priv,
 {
        struct vmw_bo *vbo;
        void *info;
+       u64 end;
        int ret;
 
        info = vmw_execbuf_info_from_res(sw_context, res);
@@ -1728,6 +1729,13 @@ static int vmw_cmd_res_switch_backup(struct vmw_private 
*dev_priv,
        if (ret)
                return ret;
 
+       if (check_add_overflow((u64)backup_offset,
+                              (u64)res->guest_memory_size, &end) ||
+           end > vbo->tbo.base.size) {
+               VMW_DEBUG_USER("Backup buffer too small for resource.\n");
+               return -EINVAL;
+       }
+
        vmw_validation_res_switch_backup(sw_context->ctx, info, vbo,
                                         backup_offset);
        return 0;
-- 
2.53.0

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to