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.
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index a48cb88..773356f 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -23,6 +23,57 @@
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 @@
{
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 @@
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,23 +283,13 @@
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++;
VIA_WRITE(offset, value);
diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h
index 5b12149..a90366f 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 @@
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 291cc76..4ec0124 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 096e3e1..84b818b 100644
--- a/shared-core/via_map.c
+++ b/shared-core/via_map.c
@@ -124,7 +124,7 @@
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 c08385c..169ad26 100644
--- a/shared-core/via_mm.c
+++ b/shared-core/via_mm.c
@@ -77,7 +77,7 @@
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 @@
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 4afc521..d9a1fb1 100644
--- a/shared/via_dma.c
+++ b/shared/via_dma.c
@@ -24,6 +24,57 @@
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 @@
{
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 @@
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 @@
return 0;
}
+
static int via_parse_pci_cmdbuffer( drm_device_t *dev, const char *buf,
unsigned int size )
{
@@ -232,22 +290,12 @@
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 ddc89f8..52adade 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 @@
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 7b6e1b9..ebff300 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 f08503d..7d3ebf2 100644
--- a/shared/via_map.c
+++ b/shared/via_map.c
@@ -127,7 +127,7 @@
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 2a9be68..5a30e30 100644
--- a/shared/via_mm.c
+++ b/shared/via_mm.c
@@ -80,7 +80,7 @@
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 @@
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;
}