diff options
-rw-r--r-- | shared-core/via_dma.c | 75 | ||||
-rw-r--r-- | shared-core/via_drm.h | 23 | ||||
-rw-r--r-- | shared-core/via_drv.c | 6 | ||||
-rw-r--r-- | shared-core/via_map.c | 2 | ||||
-rw-r--r-- | shared-core/via_mm.c | 4 | ||||
-rw-r--r-- | shared/via_dma.c | 76 | ||||
-rw-r--r-- | shared/via_drm.h | 23 | ||||
-rw-r--r-- | shared/via_drv.c | 6 | ||||
-rw-r--r-- | shared/via_map.c | 2 | ||||
-rw-r--r-- | shared/via_mm.c | 4 |
10 files changed, 157 insertions, 64 deletions
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<size; ++i) { + offset = *buf; + buf += 2; + if ((offset > ((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++; diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h index 5b121491..a90366ff 100644 --- a/shared-core/via_drm.h +++ b/shared-core/via_drm.h @@ -101,19 +101,19 @@ #define VIDEO 0 #define AGP 1 typedef struct { - unsigned int offset; - unsigned int size; + uint32_t offset; + uint32_t size; } drm_via_agp_t; typedef struct { - unsigned int offset; - unsigned int size; + uint32_t offset; + uint32_t size; } drm_via_fb_t; typedef struct { - unsigned int context; - unsigned int type; - unsigned int size; + uint32_t context; + uint32_t type; + uint32_t size; unsigned long index; unsigned long offset; } drm_via_mem_t; @@ -134,11 +134,10 @@ typedef struct _drm_via_futex { enum { VIA_FUTEX_WAIT = 0x00, VIA_FUTEX_WAKE = 0X01 - } fut; - unsigned int op; - unsigned int ms; - unsigned int lock; - unsigned int val; + } func; + uint32_t ms; + uint32_t lock; + uint32_t val; } drm_via_futex_t; typedef struct _drm_via_dma_init { diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c index 291cc76e..4ec0124c 100644 --- a/shared-core/via_drv.c +++ b/shared-core/via_drv.c @@ -31,10 +31,10 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome" -#define DRIVER_DATE "20040907" +#define DRIVER_DATE "20041010" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 5 +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 #include "drm_pciids.h" diff --git a/shared-core/via_map.c b/shared-core/via_map.c index 096e3e15..84b818b0 100644 --- a/shared-core/via_map.c +++ b/shared-core/via_map.c @@ -124,7 +124,7 @@ int via_decoder_futex(DRM_IOCTL_ARGS) lock = XVMCLOCKPTR(sAPriv, fx.lock); - switch (fx.op) { + switch (fx.func) { case VIA_FUTEX_WAIT: DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock], (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val); diff --git a/shared-core/via_mm.c b/shared-core/via_mm.c index c08385ce..169ad26e 100644 --- a/shared-core/via_mm.c +++ b/shared-core/via_mm.c @@ -77,7 +77,7 @@ int via_agp_init(DRM_IOCTL_ARGS) AgpHeap = via_mmInit(agp.offset, agp.size); - DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + DRM_DEBUG("offset = %lu, size = %lu", agp.offset, agp.size); return 0; } @@ -93,7 +93,7 @@ int via_fb_init(DRM_IOCTL_ARGS) FBHeap = via_mmInit(fb.offset, fb.size); - DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + DRM_DEBUG("offset = %lu, size = %lu", fb.offset, fb.size); return 0; } diff --git a/shared/via_dma.c b/shared/via_dma.c index 4afc5215..d9a1fb1a 100644 --- a/shared/via_dma.c +++ b/shared/via_dma.c @@ -24,6 +24,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<size; ++i) { + offset = *buf; + buf += 2; + if ((offset > ((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) { @@ -163,6 +214,8 @@ static int via_dispatch_cmdbuffer(drm_device_t *dev, { 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); @@ -170,6 +223,10 @@ static int via_dispatch_cmdbuffer(drm_device_t *dev, 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); @@ -225,6 +282,7 @@ int via_cmdbuffer( DRM_IOCTL_ARGS ) return 0; } + static int via_parse_pci_cmdbuffer( drm_device_t *dev, const char *buf, unsigned int size ) { @@ -232,22 +290,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; + if ((ret = via_check_command_stream( regbuf, size))) + return 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 ); - } - } - - regbuf = (uint32_t *)buf; for ( i=0; i<size; ++i ) { offset = (*regbuf++ & ~VIA_2D_CMD) << 2; value = *regbuf++; diff --git a/shared/via_drm.h b/shared/via_drm.h index ddc89f83..52adade2 100644 --- a/shared/via_drm.h +++ b/shared/via_drm.h @@ -90,19 +90,19 @@ #define VIDEO 0 #define AGP 1 typedef struct { - unsigned int offset; - unsigned int size; + unsigned long offset; + unsigned long size; } drm_via_agp_t; typedef struct { - unsigned int offset; - unsigned int size; + unsigned long offset; + unsigned long size; } drm_via_fb_t; typedef struct { - unsigned int context; - unsigned int type; - unsigned int size; + uint32_t context; + uint32_t type; + unsigned long size; unsigned long index; unsigned long offset; } drm_via_mem_t; @@ -123,11 +123,10 @@ typedef struct _drm_via_futex { enum { VIA_FUTEX_WAIT = 0x00, VIA_FUTEX_WAKE = 0X01 - }fut; - unsigned int op; - unsigned int ms; - unsigned int lock; - unsigned int val; + } func; + uint32_t ms; + uint32_t lock; + uint32_t val; } drm_via_futex_t; typedef struct _drm_via_dma_init { diff --git a/shared/via_drv.c b/shared/via_drv.c index 7b6e1b96..ebff3007 100644 --- a/shared/via_drv.c +++ b/shared/via_drv.c @@ -32,10 +32,10 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome" -#define DRIVER_DATE "20040907" +#define DRIVER_DATE "20041010" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 5 +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 diff --git a/shared/via_map.c b/shared/via_map.c index f08503d4..7d3ebf26 100644 --- a/shared/via_map.c +++ b/shared/via_map.c @@ -127,7 +127,7 @@ int via_decoder_futex( DRM_IOCTL_ARGS ) lock = XVMCLOCKPTR(sAPriv,fx.lock); - switch(fx.op) { + switch(fx.func) { case VIA_FUTEX_WAIT: DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock], (fx.ms / 10)*(DRM_HZ/100), diff --git a/shared/via_mm.c b/shared/via_mm.c index 2a9be681..5a30e30d 100644 --- a/shared/via_mm.c +++ b/shared/via_mm.c @@ -80,7 +80,7 @@ int via_agp_init( DRM_IOCTL_ARGS ) AgpHeap = via_mmInit(agp.offset, agp.size); - DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + DRM_DEBUG("offset = %lu, size = %lu", agp.offset, agp.size); return 0; } @@ -97,7 +97,7 @@ int via_fb_init( DRM_IOCTL_ARGS ) FBHeap = via_mmInit(fb.offset, fb.size); - DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + DRM_DEBUG("offset = %lu, size = %lu", fb.offset, fb.size); return 0; } |