Commit 50a1d632 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] i830 DRM missing put_user

From: Arjan van de Ven <arjanv@redhat.com>

The patch below adds a few missing put_user()'s to the i810/i830 drm
modules.  Users reported oopses with 4g/4g split in action, and sparse
annotations indeed found the offender in the function in question.  I've
kept the sparse __user annotations since those are generally useful anyway.
 I can't test it myself but a few people reported that the oopses went away
so far.
parent 1079b187
...@@ -844,11 +844,13 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, ...@@ -844,11 +844,13 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
if (buf_priv->currently_mapped == I810_BUF_MAPPED) { if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
*(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | put_user((GFX_OP_PRIMITIVE | prim |
((used/4)-2)); ((used/4)-2)),
(u32 *)buf_priv->virtual);
if (used & 4) { if (used & 4) {
*(u32 *)((u32)buf_priv->virtual + used) = 0; put_user(0,
(u32 *)((u32)buf_priv->virtual + used));
used += 4; used += 4;
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/interrupt.h> /* For task queue support */ #include <linux/interrupt.h> /* For task queue support */
#include <linux/pagemap.h> /* For FASTCALL on unlock_page() */ #include <linux/pagemap.h> /* For FASTCALL on unlock_page() */
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/uaccess.h>
#define I830_BUF_FREE 2 #define I830_BUF_FREE 2
#define I830_BUF_CLIENT 1 #define I830_BUF_CLIENT 1
...@@ -160,7 +161,7 @@ static int i830_map_buffer(drm_buf_t *buf, struct file *filp) ...@@ -160,7 +161,7 @@ static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
old_fops = filp->f_op; old_fops = filp->f_op;
filp->f_op = &i830_buffer_fops; filp->f_op = &i830_buffer_fops;
dev_priv->mmap_buffer = buf; dev_priv->mmap_buffer = buf;
buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, buf_priv->virtual = (void __user *)do_mmap(filp, 0, buf->total,
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_SHARED, MAP_SHARED,
buf->bus_address); buf->bus_address);
...@@ -462,7 +463,7 @@ static int i830_dma_initialize(drm_device_t *dev, ...@@ -462,7 +463,7 @@ static int i830_dma_initialize(drm_device_t *dev,
} }
int i830_dma_init(struct inode *inode, struct file *filp, int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -470,7 +471,7 @@ int i830_dma_init(struct inode *inode, struct file *filp, ...@@ -470,7 +471,7 @@ int i830_dma_init(struct inode *inode, struct file *filp,
drm_i830_init_t init; drm_i830_init_t init;
int retcode = 0; int retcode = 0;
if (copy_from_user(&init, (drm_i830_init_t *)arg, sizeof(init))) if (copy_from_user(&init, (void * __user) arg, sizeof(init)))
return -EFAULT; return -EFAULT;
switch(init.func) { switch(init.func) {
...@@ -1166,17 +1167,17 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev, ...@@ -1166,17 +1167,17 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
if (buf_priv->currently_mapped == I830_BUF_MAPPED) { if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
u32 *vp = buf_priv->virtual; u32 *vp = buf_priv->virtual;
vp[0] = (GFX_OP_PRIMITIVE | put_user( (GFX_OP_PRIMITIVE |
sarea_priv->vertex_prim | sarea_priv->vertex_prim |
((used/4)-2)); ((used/4)-2)), &vp[0]);
if (dev_priv->use_mi_batchbuffer_start) { if (dev_priv->use_mi_batchbuffer_start) {
vp[used/4] = MI_BATCH_BUFFER_END; put_user(MI_BATCH_BUFFER_END, &vp[used/4]);
used += 4; used += 4;
} }
if (used & 4) { if (used & 4) {
vp[used/4] = 0; put_user(0, &vp[used/4]);
used += 4; used += 4;
} }
...@@ -1314,7 +1315,7 @@ void i830_reclaim_buffers( struct file *filp ) ...@@ -1314,7 +1315,7 @@ void i830_reclaim_buffers( struct file *filp )
} }
int i830_flush_ioctl(struct inode *inode, struct file *filp, int i830_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1329,7 +1330,7 @@ int i830_flush_ioctl(struct inode *inode, struct file *filp, ...@@ -1329,7 +1330,7 @@ int i830_flush_ioctl(struct inode *inode, struct file *filp,
} }
int i830_dma_vertex(struct inode *inode, struct file *filp, int i830_dma_vertex(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1340,7 +1341,7 @@ int i830_dma_vertex(struct inode *inode, struct file *filp, ...@@ -1340,7 +1341,7 @@ int i830_dma_vertex(struct inode *inode, struct file *filp,
dev_priv->sarea_priv; dev_priv->sarea_priv;
drm_i830_vertex_t vertex; drm_i830_vertex_t vertex;
if (copy_from_user(&vertex, (drm_i830_vertex_t *)arg, sizeof(vertex))) if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))
return -EFAULT; return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
...@@ -1364,13 +1365,13 @@ int i830_dma_vertex(struct inode *inode, struct file *filp, ...@@ -1364,13 +1365,13 @@ int i830_dma_vertex(struct inode *inode, struct file *filp,
} }
int i830_clear_bufs(struct inode *inode, struct file *filp, int i830_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
drm_i830_clear_t clear; drm_i830_clear_t clear;
if (copy_from_user(&clear, (drm_i830_clear_t *)arg, sizeof(clear))) if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
return -EFAULT; return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
...@@ -1391,7 +1392,7 @@ int i830_clear_bufs(struct inode *inode, struct file *filp, ...@@ -1391,7 +1392,7 @@ int i830_clear_bufs(struct inode *inode, struct file *filp,
} }
int i830_swap_bufs(struct inode *inode, struct file *filp, int i830_swap_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1434,7 +1435,7 @@ int i830_do_cleanup_pageflip( drm_device_t *dev ) ...@@ -1434,7 +1435,7 @@ int i830_do_cleanup_pageflip( drm_device_t *dev )
} }
int i830_flip_bufs(struct inode *inode, struct file *filp, int i830_flip_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1455,7 +1456,7 @@ int i830_flip_bufs(struct inode *inode, struct file *filp, ...@@ -1455,7 +1456,7 @@ int i830_flip_bufs(struct inode *inode, struct file *filp,
} }
int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg) unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1469,7 +1470,7 @@ int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1469,7 +1470,7 @@ int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
} }
int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg) unsigned long __user arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1481,7 +1482,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1481,7 +1482,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
dev_priv->sarea_priv; dev_priv->sarea_priv;
DRM_DEBUG("getbuf\n"); DRM_DEBUG("getbuf\n");
if (copy_from_user(&d, (drm_i830_dma_t *)arg, sizeof(d))) if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))
return -EFAULT; return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
...@@ -1496,7 +1497,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1496,7 +1497,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted); current->pid, retcode, d.granted);
if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
return -EFAULT; return -EFAULT;
sarea_priv->last_dispatch = (int) hw_status[5]; sarea_priv->last_dispatch = (int) hw_status[5];
...@@ -1506,7 +1507,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1506,7 +1507,7 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
int i830_copybuf(struct inode *inode, int i830_copybuf(struct inode *inode,
struct file *filp, struct file *filp,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long __user arg)
{ {
/* Never copy - 2.4.x doesn't need it */ /* Never copy - 2.4.x doesn't need it */
return 0; return 0;
...@@ -1521,7 +1522,7 @@ int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1521,7 +1522,7 @@ int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd, int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg ) unsigned long __user arg )
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1534,7 +1535,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1534,7 +1535,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL; return -EINVAL;
} }
if (copy_from_user(&param, (drm_i830_getparam_t *)arg, sizeof(param) )) if (copy_from_user(&param, (drm_i830_getparam_t __user *)arg, sizeof(param) ))
return -EFAULT; return -EFAULT;
switch( param.param ) { switch( param.param ) {
...@@ -1555,7 +1556,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1555,7 +1556,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd, int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg ) unsigned long __user arg )
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
...@@ -1567,7 +1568,7 @@ int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -1567,7 +1568,7 @@ int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL; return -EINVAL;
} }
if (copy_from_user(&param, (drm_i830_setparam_t *)arg, sizeof(param) )) if (copy_from_user(&param, (drm_i830_setparam_t __user *)arg, sizeof(param) ))
return -EFAULT; return -EFAULT;
switch( param.param ) { switch( param.param ) {
......
...@@ -290,11 +290,11 @@ typedef struct _drm_i830_vertex { ...@@ -290,11 +290,11 @@ typedef struct _drm_i830_vertex {
typedef struct _drm_i830_copy_t { typedef struct _drm_i830_copy_t {
int idx; /* buffer index */ int idx; /* buffer index */
int used; /* nr bytes in use */ int used; /* nr bytes in use */
void *address; /* Address to copy from */ void __user *address; /* Address to copy from */
} drm_i830_copy_t; } drm_i830_copy_t;
typedef struct drm_i830_dma { typedef struct drm_i830_dma {
void *virtual; void __user *virtual;
int request_idx; int request_idx;
int request_size; int request_size;
int granted; int granted;
...@@ -304,7 +304,7 @@ typedef struct drm_i830_dma { ...@@ -304,7 +304,7 @@ typedef struct drm_i830_dma {
/* 1.3: Userspace can request & wait on irq's: /* 1.3: Userspace can request & wait on irq's:
*/ */
typedef struct drm_i830_irq_emit { typedef struct drm_i830_irq_emit {
int *irq_seq; int __user *irq_seq;
} drm_i830_irq_emit_t; } drm_i830_irq_emit_t;
typedef struct drm_i830_irq_wait { typedef struct drm_i830_irq_wait {
...@@ -318,7 +318,7 @@ typedef struct drm_i830_irq_wait { ...@@ -318,7 +318,7 @@ typedef struct drm_i830_irq_wait {
typedef struct drm_i830_getparam { typedef struct drm_i830_getparam {
int param; int param;
int *value; int __user *value;
} drm_i830_getparam_t; } drm_i830_getparam_t;
......
...@@ -36,7 +36,7 @@ typedef struct drm_i830_buf_priv { ...@@ -36,7 +36,7 @@ typedef struct drm_i830_buf_priv {
u32 *in_use; u32 *in_use;
int my_use_idx; int my_use_idx;
int currently_mapped; int currently_mapped;
void *virtual; void __user *virtual;
void *kernel_virtual; void *kernel_virtual;
} drm_i830_buf_priv_t; } drm_i830_buf_priv_t;
......
...@@ -121,7 +121,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr) ...@@ -121,7 +121,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr)
/* Needs the lock as it touches the ring. /* Needs the lock as it touches the ring.
*/ */
int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd, int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg ) unsigned long __user arg )
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
......
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