fixes for using userspace pointers found by sparse utility
authorDave Airlie <airlied@linux.ie>
Sat, 31 Jul 2004 07:26:52 +0000 (07:26 +0000)
committerDave Airlie <airlied@linux.ie>
Sat, 31 Jul 2004 07:26:52 +0000 (07:26 +0000)
From: Dave Airlie

linux/gamma_old_dma.h
shared-core/i915_dma.c
shared-core/i915_mem.c
shared/i915_dma.c
shared/i915_mem.c

index 43be5c8..54bc11f 100644 (file)
@@ -121,7 +121,10 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
        drm_buf_t         *buf;
        int               idx;
        int               while_locked = 0;
+       int               retcode   = 0;
        drm_device_dma_t  *dma = dev->dma;
+       int               *send_indices = NULL;
+       int               *send_sizes = NULL;
        DECLARE_WAITQUEUE(entry, current);
 
        DRM_DEBUG("%d\n", d->send_count);
@@ -168,45 +171,66 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
                remove_wait_queue(&q->write_queue, &entry);
        }
 
+       send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
+                                 DRM_MEM_DRIVER);
+       if (send_indices == NULL)
+               return -ENOMEM;
+       if (copy_from_user(send_indices, d->send_indices, 
+                          d->send_count * sizeof(*send_indices))) {
+               retcode = -EFAULT;
+                goto cleanup;
+       }
+       
+       send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
+                               DRM_MEM_DRIVER);
+       if (send_sizes == NULL)
+               return -ENOMEM;
+       if (copy_from_user(send_sizes, d->send_sizes, 
+                          d->send_count * sizeof(*send_sizes))) {
+               retcode = -EFAULT;
+                goto cleanup;
+       }
+
        for (i = 0; i < d->send_count; i++) {
-               idx = d->send_indices[i];
+               idx = send_indices[i];
                if (idx < 0 || idx >= dma->buf_count) {
-                       atomic_dec(&q->use_count);
                        DRM_ERROR("Index %d (of %d max)\n",
-                                 d->send_indices[i], dma->buf_count - 1);
-                       return -EINVAL;
+                                 send_indices[i], dma->buf_count - 1);
+                       retcode = -EINVAL;
+                       goto cleanup;
                }
                buf = dma->buflist[ idx ];
                if (buf->filp != filp) {
-                       atomic_dec(&q->use_count);
                        DRM_ERROR("Process %d using buffer not owned\n",
                                  current->pid);
-                       return -EINVAL;
+                       retcode = -EINVAL;
+                       goto cleanup;
                }
                if (buf->list != DRM_LIST_NONE) {
-                       atomic_dec(&q->use_count);
                        DRM_ERROR("Process %d using buffer %d on list %d\n",
                                  current->pid, buf->idx, buf->list);
+                       retcode = -EINVAL;
+                       goto cleanup;
                }
-               buf->used         = d->send_sizes[i];
+               buf->used         = send_sizes[i];
                buf->while_locked = while_locked;
                buf->context      = d->context;
                if (!buf->used) {
                        DRM_ERROR("Queueing 0 length buffer\n");
                }
                if (buf->pending) {
-                       atomic_dec(&q->use_count);
                        DRM_ERROR("Queueing pending buffer:"
                                  " buffer %d, offset %d\n",
-                                 d->send_indices[i], i);
-                       return -EINVAL;
+                                 send_indices[i], i);
+                       retcode = -EINVAL;
+                       goto cleanup;
                }
                if (buf->waiting) {
-                       atomic_dec(&q->use_count);
                        DRM_ERROR("Queueing waiting buffer:"
                                  " buffer %d, offset %d\n",
-                                 d->send_indices[i], i);
-                       return -EINVAL;
+                                 send_indices[i], i);
+                       retcode = -EINVAL;
+                       goto cleanup;
                }
                buf->waiting = 1;
                if (atomic_read(&q->use_count) == 1
@@ -217,9 +241,15 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
                        atomic_inc(&q->total_queued);
                }
        }
+cleanup:
+       if (send_indices)
+               DRM(free)(send_indices, d->send_count * sizeof(*send_indices), 
+                         DRM_MEM_DRIVER);
+       if (send_sizes)
+               DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes), 
+                         DRM_MEM_DRIVER);
        atomic_dec(&q->use_count);
-
-       return 0;
+       return retcode;
 }
 
 static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
index e7364ff..2882037 100644 (file)
@@ -471,7 +471,7 @@ static int i915_dispatch_batchbuffer(drm_device_t *dev,
                                    drm_i915_batchbuffer_t *batch )
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t *boxes = batch->cliprects;
+       drm_clip_rect_t __user *boxes = batch->cliprects;
        int nbox = batch->num_cliprects;
        int i = 0, count;
        RING_LOCALS;
index 2a2379d..4009851 100644 (file)
@@ -237,7 +237,7 @@ void i915_mem_takedown( struct mem_block **heap )
        }
 
        DRM_FREE( *heap, sizeof(**heap) );
-       *heap = 0;
+       *heap = NULL;
 }
 
 
@@ -249,7 +249,7 @@ static struct mem_block **get_heap( drm_i915_private_t *dev_priv,
        case I915_MEM_REGION_AGP:
                return &dev_priv->agp_heap; 
        default:
-               return 0;
+               return NULL;
        }
 }
 
index e7364ff..2882037 100644 (file)
@@ -471,7 +471,7 @@ static int i915_dispatch_batchbuffer(drm_device_t *dev,
                                    drm_i915_batchbuffer_t *batch )
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t *boxes = batch->cliprects;
+       drm_clip_rect_t __user *boxes = batch->cliprects;
        int nbox = batch->num_cliprects;
        int i = 0, count;
        RING_LOCALS;
index 2a2379d..4009851 100644 (file)
@@ -237,7 +237,7 @@ void i915_mem_takedown( struct mem_block **heap )
        }
 
        DRM_FREE( *heap, sizeof(**heap) );
-       *heap = 0;
+       *heap = NULL;
 }
 
 
@@ -249,7 +249,7 @@ static struct mem_block **get_heap( drm_i915_private_t *dev_priv,
        case I915_MEM_REGION_AGP:
                return &dev_priv->agp_heap; 
        default:
-               return 0;
+               return NULL;
        }
 }