Commit de8217c6 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] drm/gamma_old_dma.h fix

blind dereferencing of userland pointer
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e9a58c69
...@@ -122,6 +122,8 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d) ...@@ -122,6 +122,8 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
int idx; int idx;
int while_locked = 0; int while_locked = 0;
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
int *ind;
int err;
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
DRM_DEBUG("%d\n", d->send_count); DRM_DEBUG("%d\n", d->send_count);
...@@ -168,45 +170,51 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d) ...@@ -168,45 +170,51 @@ 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);
} }
ind = DRM(alloc)(d->send_count * sizeof(int), DRM_MEM_DRIVER);
if (!ind)
return -ENOMEM;
if (copy_from_user(ind, d->send_indices, d->send_count * sizeof(int))) {
err = -EFAULT;
goto out;
}
err = -EINVAL;
for (i = 0; i < d->send_count; i++) { for (i = 0; i < d->send_count; i++) {
idx = d->send_indices[i]; idx = ind[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); ind[i], dma->buf_count - 1);
return -EINVAL; goto out;
} }
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; goto out;
} }
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);
goto out;
} }
buf->used = d->send_sizes[i]; buf->used = ind[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); ind[i], i);
return -EINVAL; goto out;
} }
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); ind[i], i);
return -EINVAL; goto out;
} }
buf->waiting = 1; buf->waiting = 1;
if (atomic_read(&q->use_count) == 1 if (atomic_read(&q->use_count) == 1
...@@ -220,6 +228,11 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d) ...@@ -220,6 +228,11 @@ int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
atomic_dec(&q->use_count); atomic_dec(&q->use_count);
return 0; return 0;
out:
DRM(free)(ind, d->send_count * sizeof(int), DRM_MEM_DRIVER);
atomic_dec(&q->use_count);
return err;
} }
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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment