aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2014-04-15 18:25:48 +0200
committerBen Hutchings <ben@decadent.org.uk>2014-06-09 13:29:01 +0100
commit98077594d9f33566c0681c0944fdcaed3e113ad0 (patch)
tree116d8af9784bdf28915a9b21e3bba1ee830b4903 /drivers/gpu/drm
parent0ea6c9718b30594df91ece10533f6faee355abfc (diff)
downloadkernel_samsung_smdk4412-98077594d9f33566c0681c0944fdcaed3e113ad0.zip
kernel_samsung_smdk4412-98077594d9f33566c0681c0944fdcaed3e113ad0.tar.gz
kernel_samsung_smdk4412-98077594d9f33566c0681c0944fdcaed3e113ad0.tar.bz2
drm/vmwgfx: Make sure user-space can't DMA across buffer object boundaries v2
commit cbd75e97a525e3819c02dc18bc2d67aa544c9e45 upstream. 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> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 40932fb..84ba033 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -558,14 +558,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
} *cmd;
int ret;
struct vmw_resource *res;
+ 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;
+
bo = &vmw_bo->base;
ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
cmd->dma.host.sid, &srf);