diff options
author | Dave Airlie <airlied@redhat.com> | 2014-04-30 09:43:43 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-04-30 09:43:43 +1000 |
commit | d8af20bcae25e8792ccd8c94404e6e57e7db75f2 (patch) | |
tree | b58cc8e2865ed7a25a9922344da5e7130d7baada /drivers | |
parent | 917db410450e265b82ac36ad1cbbfd5f3ca9a204 (diff) | |
parent | cbd75e97a525e3819c02dc18bc2d67aa544c9e45 (diff) |
Merge branch 'vmwgfx-fixes-3.15' of git://people.freedesktop.org/~thomash/linux into drm-next
single security fix, cc'd stable.
* 'vmwgfx-fixes-3.15' of git://people.freedesktop.org/~thomash/linux:
drm/vmwgfx: Make sure user-space can't DMA across buffer object boundaries v2
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 22 |
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 931490b9cfed..87df0b3674fd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -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); |