diff options
author | Dave Airlie <airlied@linux.ie> | 2004-07-31 07:26:52 +0000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2004-07-31 07:26:52 +0000 |
commit | eb3d0635d4830969d10d5fe8aef17cebb2f3fd15 (patch) | |
tree | d48d455b9c8d04aa8b8a76992c2449a4208e64f8 /linux/gamma_old_dma.h | |
parent | dc4508c33845602e4c94c3e125536d01fe9110b1 (diff) |
fixes for using userspace pointers found by sparse utility
From: Dave Airlie
Diffstat (limited to 'linux/gamma_old_dma.h')
-rw-r--r-- | linux/gamma_old_dma.h | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/linux/gamma_old_dma.h b/linux/gamma_old_dma.h index 43be5c80..54bc11f9 100644 --- a/linux/gamma_old_dma.h +++ b/linux/gamma_old_dma.h @@ -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, |