summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2014-11-16 11:00:35 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2014-11-16 11:00:35 +0100
commitd79ede622ee95083904e42d15e748f1441eb1732 (patch)
treebae9d4a6734cff56228bf9ca9a68e3544c229ed5
parent35c21d966374068fdfb32d94c345ac06ac0d6bde (diff)
vmwgfx: Make sure user-space can't DMA across buffer object boundaries v2
We already check that the buffer object we're accessing is registered with the file. Now also make sure that we can't DMA across buffer object boundaries. v2: Code commenting update. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
-rw-r--r--vmwgfx_execbuf.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/vmwgfx_execbuf.c b/vmwgfx_execbuf.c
index d4fb29b..55828b2 100644
--- a/vmwgfx_execbuf.c
+++ b/vmwgfx_execbuf.c
@@ -1244,14 +1244,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);