summaryrefslogtreecommitdiff
path: root/shared-core/via_dma.c
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2004-10-08 21:11:02 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2004-10-08 21:11:02 +0000
commitd24194e904cbfc85147efae6922e497e0102b2eb (patch)
tree797dbd6e2131d7d1f7d49b22cbd761153a15b43f /shared-core/via_dma.c
parent3981f17227aa72b263d27e79aede307b1e2980a8 (diff)
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.
Diffstat (limited to 'shared-core/via_dma.c')
-rw-r--r--shared-core/via_dma.c75
1 files changed, 61 insertions, 14 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++;