|
@@ -1214,14 +1214,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
|
|
|
SVGA3dCmdSurfaceDMA dma;
|
|
|
} *cmd;
|
|
|
int ret;
|
|
|
+ SVGA3dCmdSurfaceDMASuffix *suffix;
|
|
|
+ uint32_t bo_size;
|
|
|
|
|
|
cmd = container_of(header, struct vmw_dma_cmd, header);
|
|
|
+ suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma +
|
|
|
+ header->size - sizeof(*suffix));
|
|
|
+
|
|
|
+ /* Make sure device and verifier stays in sync. */
|
|
|
+ if (unlikely(suffix->suffixSize != sizeof(*suffix))) {
|
|
|
+ DRM_ERROR("Invalid DMA suffix size.\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
ret = vmw_translate_guest_ptr(dev_priv, sw_context,
|
|
|
&cmd->dma.guest.ptr,
|
|
|
&vmw_bo);
|
|
|
if (unlikely(ret != 0))
|
|
|
return ret;
|
|
|
|
|
|
+ /* Make sure DMA doesn't cross BO boundaries. */
|
|
|
+ bo_size = vmw_bo->base.num_pages * PAGE_SIZE;
|
|
|
+ if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) {
|
|
|
+ DRM_ERROR("Invalid DMA offset.\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ bo_size -= cmd->dma.guest.ptr.offset;
|
|
|
+ if (unlikely(suffix->maximumOffset > bo_size))
|
|
|
+ suffix->maximumOffset = bo_size;
|
|
|
+
|
|
|
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
|
|
|
user_surface_converter, &cmd->dma.host.sid,
|
|
|
NULL);
|