From d24194e904cbfc85147efae6922e497e0102b2eb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 8 Oct 2004 21:11:02 +0000 Subject: Changed unsigned to uint32_t in some ioctl parameters. Introduced first rudimentary command verifier for dma buffers. Changed the decoder futex ioctl parameters. Bumped the via major version number. --- shared-core/via_dma.c | 75 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 14 deletions(-) (limited to 'shared-core/via_dma.c') diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index a48cb883..773356fb 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -23,6 +23,57 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv); static void via_cmdbuf_rewind(drm_via_private_t * dev_priv); static int via_wait_idle(drm_via_private_t * dev_priv); + +/* + * This function needs to be extended whenever a new command set + * is implemented. Currently it works only for the 2D engine + * command, which on the Unichrome allows writing to + * at least the 2D engine and the mpeg engine, but not the + * video engine. + * + * If you update this function with new commands, please also + * consider implementing these commands in + * via_parse_pci_cmdbuffer below. + * + * Carefully review this function for security holes + * after an update!!!!!!!!! + */ + +static int via_check_command_stream(const uint32_t *buf, + unsigned int size) +{ + + uint32_t offset; + unsigned int i; + + if (size & 7) { + DRM_ERROR("Illegal command buffer size.\n"); + return DRM_ERR( EINVAL ); + } + size >>=3; + for (i=0; i ((0x3FF >> 2) | VIA_2D_CMD)) && + (offset < ((0xC00 >> 2) | VIA_2D_CMD)) ) { + DRM_ERROR("Attempt to access Burst Command / 3D Area.\n"); + return DRM_ERR( EINVAL ); + } else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) { + DRM_ERROR("Attempt to access DMA or VGA registers.\n"); + return DRM_ERR( EINVAL ); + } + + /* + * ... + * A volunteer should complete this to allow non-root + * usage of accelerated 3D OpenGL. + */ + + } + return 0; +} + + static inline int via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size) { @@ -160,6 +211,8 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) { drm_via_private_t *dev_priv = dev->dev_private; uint32_t *vb; + int ret; + vb = via_check_dma(dev_priv, cmd->size); if (vb == NULL) { return DRM_ERR(EAGAIN); @@ -167,6 +220,10 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) if (DRM_COPY_FROM_USER(vb, cmd->buf, cmd->size)) { return DRM_ERR(EFAULT); } + + if ((ret = via_check_command_stream( vb, cmd->size))) + return ret; + dev_priv->dma_low += cmd->size; via_cmdbuf_pause(dev_priv); @@ -226,22 +283,12 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, uint32_t offset, value; const uint32_t *regbuf = (uint32_t *) buf; unsigned int i; + int ret; - size >>= 3; - for (i = 0; i < size; ++i) { - offset = *regbuf; - regbuf += 2; - if ((offset > ((0x7FF >> 2) | VIA_2D_CMD)) && - (offset < ((0xC00 >> 2) | VIA_2D_CMD))) { - DRM_DEBUG("Attempt to access Burst Command Area.\n"); - return DRM_ERR(EINVAL); - } else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) { - DRM_DEBUG("Attempt to access DMA or VGA registers.\n"); - return DRM_ERR(EINVAL); - } - } + if ((ret = via_check_command_stream( regbuf, size))) + return ret; - regbuf = (uint32_t *) buf; + size >>= 3; for (i = 0; i < size; ++i) { offset = (*regbuf++ & ~VIA_2D_CMD) << 2; value = *regbuf++; -- cgit v1.2.3