From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Thomas Hellstrom , Jakob Bornecrantz Subject: [PATCH 3.10 35/86] drm/vmwgfx: Make sure user-space cant DMA across buffer object boundaries v2 Date: Wed, 28 May 2014 21:37:10 -0700 Message-Id: <20140529043518.229625541@linuxfoundation.org> In-Reply-To: <20140529043513.451722422@linuxfoundation.org> References: <20140529043513.451722422@linuxfoundation.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: 3.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Thomas Hellstrom 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 Reviewed-by: Jakob Bornecrantz Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -834,14 +834,36 @@ static int vmw_cmd_dma(struct vmw_privat 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);