fixes for using userspace pointers found by sparse utility

From: Dave Airlie
main
Dave Airlie 2004-07-31 07:26:52 +00:00
parent dc4508c338
commit eb3d0635d4
5 changed files with 52 additions and 22 deletions

View File

@ -121,7 +121,10 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
drm_buf_t *buf; drm_buf_t *buf;
int idx; int idx;
int while_locked = 0; int while_locked = 0;
int retcode = 0;
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
int *send_indices = NULL;
int *send_sizes = NULL;
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
DRM_DEBUG("%d\n", d->send_count); 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); 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++) { for (i = 0; i < d->send_count; i++) {
idx = d->send_indices[i]; idx = send_indices[i];
if (idx < 0 || idx >= dma->buf_count) { if (idx < 0 || idx >= dma->buf_count) {
atomic_dec(&q->use_count);
DRM_ERROR("Index %d (of %d max)\n", DRM_ERROR("Index %d (of %d max)\n",
d->send_indices[i], dma->buf_count - 1); send_indices[i], dma->buf_count - 1);
return -EINVAL; retcode = -EINVAL;
goto cleanup;
} }
buf = dma->buflist[ idx ]; buf = dma->buflist[ idx ];
if (buf->filp != filp) { if (buf->filp != filp) {
atomic_dec(&q->use_count);
DRM_ERROR("Process %d using buffer not owned\n", DRM_ERROR("Process %d using buffer not owned\n",
current->pid); current->pid);
return -EINVAL; retcode = -EINVAL;
goto cleanup;
} }
if (buf->list != DRM_LIST_NONE) { if (buf->list != DRM_LIST_NONE) {
atomic_dec(&q->use_count);
DRM_ERROR("Process %d using buffer %d on list %d\n", DRM_ERROR("Process %d using buffer %d on list %d\n",
current->pid, buf->idx, buf->list); 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->while_locked = while_locked;
buf->context = d->context; buf->context = d->context;
if (!buf->used) { if (!buf->used) {
DRM_ERROR("Queueing 0 length buffer\n"); DRM_ERROR("Queueing 0 length buffer\n");
} }
if (buf->pending) { if (buf->pending) {
atomic_dec(&q->use_count);
DRM_ERROR("Queueing pending buffer:" DRM_ERROR("Queueing pending buffer:"
" buffer %d, offset %d\n", " buffer %d, offset %d\n",
d->send_indices[i], i); send_indices[i], i);
return -EINVAL; retcode = -EINVAL;
goto cleanup;
} }
if (buf->waiting) { if (buf->waiting) {
atomic_dec(&q->use_count);
DRM_ERROR("Queueing waiting buffer:" DRM_ERROR("Queueing waiting buffer:"
" buffer %d, offset %d\n", " buffer %d, offset %d\n",
d->send_indices[i], i); send_indices[i], i);
return -EINVAL; retcode = -EINVAL;
goto cleanup;
} }
buf->waiting = 1; buf->waiting = 1;
if (atomic_read(&q->use_count) == 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); 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); atomic_dec(&q->use_count);
return retcode;
return 0;
} }
static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d, static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,

View File

@ -471,7 +471,7 @@ static int i915_dispatch_batchbuffer(drm_device_t *dev,
drm_i915_batchbuffer_t *batch ) drm_i915_batchbuffer_t *batch )
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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 nbox = batch->num_cliprects;
int i = 0, count; int i = 0, count;
RING_LOCALS; RING_LOCALS;

View File

@ -237,7 +237,7 @@ void i915_mem_takedown( struct mem_block **heap )
} }
DRM_FREE( *heap, sizeof(**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: case I915_MEM_REGION_AGP:
return &dev_priv->agp_heap; return &dev_priv->agp_heap;
default: default:
return 0; return NULL;
} }
} }

View File

@ -471,7 +471,7 @@ static int i915_dispatch_batchbuffer(drm_device_t *dev,
drm_i915_batchbuffer_t *batch ) drm_i915_batchbuffer_t *batch )
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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 nbox = batch->num_cliprects;
int i = 0, count; int i = 0, count;
RING_LOCALS; RING_LOCALS;

View File

@ -237,7 +237,7 @@ void i915_mem_takedown( struct mem_block **heap )
} }
DRM_FREE( *heap, sizeof(**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: case I915_MEM_REGION_AGP:
return &dev_priv->agp_heap; return &dev_priv->agp_heap;
default: default:
return 0; return NULL;
} }
} }