drivers/char/*

	- fix copy_{to,from}_user error handling, thanks to Rusty to pointing this out on lkml
parent a2536452
...@@ -907,7 +907,9 @@ static int pc_write(struct tty_struct * tty, int from_user, ...@@ -907,7 +907,9 @@ static int pc_write(struct tty_struct * tty, int from_user,
----------------------------------------------------------------- */ ----------------------------------------------------------------- */
copy_from_user(ch->tmp_buf, buf, bytesAvailable); if (copy_from_user(ch->tmp_buf, buf,
bytesAvailable))
return -EFAULT;
} /* End if area verified */ } /* End if area verified */
...@@ -2999,7 +3001,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2999,7 +3001,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
di.port = boards[brd].port ; di.port = boards[brd].port ;
di.membase = boards[brd].membase ; di.membase = boards[brd].membase ;
copy_to_user((char *)arg, &di, sizeof (di)); if (copy_to_user((char *)arg, &di, sizeof (di)))
return -EFAULT;
break; break;
} /* End case DIGI_GETINFO */ } /* End case DIGI_GETINFO */
...@@ -3068,14 +3071,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -3068,14 +3071,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
{ /* Begin switch cmd */ { /* Begin switch cmd */
case TCGETS: case TCGETS:
retval = verify_area(VERIFY_WRITE, (void *)arg, if (copy_to_user((struct termios *)arg,
sizeof(struct termios)); tty->termios, sizeof(struct termios)))
return -EFAULT;
if (retval)
return(retval);
copy_to_user((struct termios *)arg,
tty->termios, sizeof(struct termios));
return(0); return(0);
case TCGETA: case TCGETA:
...@@ -3235,14 +3233,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -3235,14 +3233,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
break; break;
case DIGI_GETA: case DIGI_GETA:
if ((error= if (copy_to_user((char*)arg, &ch->digiext,
verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t)))) sizeof(digi_t)))
{ return -EFAULT;
printk(KERN_ERR "<Error> - Digi GETA failed\n");
return(error);
}
copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t));
break; break;
case DIGI_SETAW: case DIGI_SETAW:
...@@ -3263,11 +3256,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -3263,11 +3256,9 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
/* Fall Thru */ /* Fall Thru */
case DIGI_SETA: case DIGI_SETA:
if ((error = if (copy_from_user(&ch->digiext, (char*)arg,
verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t)))) sizeof(digi_t)))
return(error); return -EFAULT;
copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t));
if (ch->digiext.digi_flags & DIGI_ALTPIN) if (ch->digiext.digi_flags & DIGI_ALTPIN)
{ {
...@@ -3310,10 +3301,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -3310,10 +3301,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
memoff(ch); memoff(ch);
restore_flags(flags); restore_flags(flags);
if ((error = verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow)))) if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
return(error); return -EFAULT;
copy_to_user((char*)arg, &dflow, sizeof(dflow));
break; break;
case DIGI_SETAFLOW: case DIGI_SETAFLOW:
...@@ -3329,10 +3318,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -3329,10 +3318,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
stopc = ch->stopca; stopc = ch->stopca;
} }
if ((error = verify_area(VERIFY_READ, (char*)arg,sizeof(dflow)))) if (copy_from_user(&dflow, (char*)arg, sizeof(dflow)))
return(error); return -EFAULT;
copy_from_user(&dflow, (char*)arg, sizeof(dflow));
if (dflow.startc != startc || dflow.stopc != stopc) if (dflow.startc != startc || dflow.stopc != stopc)
{ /* Begin if setflow toggled */ { /* Begin if setflow toggled */
......
...@@ -2022,7 +2022,8 @@ static int stli_setserial(stliport_t *portp, struct serial_struct *sp) ...@@ -2022,7 +2022,8 @@ static int stli_setserial(stliport_t *portp, struct serial_struct *sp)
printk("stli_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); printk("stli_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
#endif #endif
copy_from_user(&sio, sp, sizeof(struct serial_struct)); if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
return -EFAULT;
if (!capable(CAP_SYS_ADMIN)) { if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) || if ((sio.baud_base != portp->baud_base) ||
(sio.close_delay != portp->close_delay) || (sio.close_delay != portp->close_delay) ||
...@@ -4878,11 +4879,15 @@ static ssize_t stli_memread(struct file *fp, char *buf, size_t count, loff_t *of ...@@ -4878,11 +4879,15 @@ static ssize_t stli_memread(struct file *fp, char *buf, size_t count, loff_t *of
while (size > 0) { while (size > 0) {
memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos); memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize))); n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
copy_to_user(buf, memptr, n); if (copy_to_user(buf, memptr, n)) {
count = -EFAULT;
goto out;
}
fp->f_pos += n; fp->f_pos += n;
buf += n; buf += n;
size -= n; size -= n;
} }
out:
EBRDDISABLE(brdp); EBRDDISABLE(brdp);
restore_flags(flags); restore_flags(flags);
...@@ -4930,11 +4935,15 @@ static ssize_t stli_memwrite(struct file *fp, const char *buf, size_t count, lof ...@@ -4930,11 +4935,15 @@ static ssize_t stli_memwrite(struct file *fp, const char *buf, size_t count, lof
while (size > 0) { while (size > 0) {
memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos); memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize))); n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
copy_from_user(memptr, chbuf, n); if (copy_from_user(memptr, chbuf, n)) {
count = -EFAULT;
goto out;
}
fp->f_pos += n; fp->f_pos += n;
chbuf += n; chbuf += n;
size -= n; size -= n;
} }
out:
EBRDDISABLE(brdp); EBRDDISABLE(brdp);
restore_flags(flags); restore_flags(flags);
......
...@@ -359,20 +359,15 @@ static ssize_t zf_read(struct file *file, char *buf, size_t count, ...@@ -359,20 +359,15 @@ static ssize_t zf_read(struct file *file, char *buf, size_t count,
static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int ret;
switch(cmd){ switch(cmd){
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
ret = copy_to_user((struct watchdog_info *)arg, if (copy_to_user((struct watchdog_info *)arg,
&zf_info, sizeof(zf_info)); &zf_info, sizeof(zf_info)))
if(ret)
return -EFAULT; return -EFAULT;
break; break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
ret = copy_to_user((int *)arg, &zf_is_open, if (copy_to_user((int *)arg, &zf_is_open, sizeof(int)))
sizeof(int));
if(ret)
return -EFAULT; return -EFAULT;
break; break;
......
...@@ -2175,8 +2175,7 @@ static int mxser_get_serial_info(struct mxser_struct *info, ...@@ -2175,8 +2175,7 @@ static int mxser_get_serial_info(struct mxser_struct *info,
tmp.closing_wait = info->closing_wait; tmp.closing_wait = info->closing_wait;
tmp.custom_divisor = info->custom_divisor; tmp.custom_divisor = info->custom_divisor;
tmp.hub6 = 0; tmp.hub6 = 0;
copy_to_user(retinfo, &tmp, sizeof(*retinfo)); return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
return (0);
} }
static int mxser_set_serial_info(struct mxser_struct *info, static int mxser_set_serial_info(struct mxser_struct *info,
...@@ -2188,7 +2187,8 @@ static int mxser_set_serial_info(struct mxser_struct *info, ...@@ -2188,7 +2187,8 @@ static int mxser_set_serial_info(struct mxser_struct *info,
if (!new_info || !info->base) if (!new_info || !info->base)
return (-EFAULT); return (-EFAULT);
copy_from_user(&new_serial, new_info, sizeof(new_serial)); if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
if ((new_serial.irq != info->irq) || if ((new_serial.irq != info->irq) ||
(new_serial.port != info->base) || (new_serial.port != info->base) ||
......
...@@ -1364,7 +1364,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, ...@@ -1364,7 +1364,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
pHeader->owner = pClient; pHeader->owner = pClient;
} }
copy_from_user (pHeader->data, data, count); /* We already verified this */ __copy_from_user(pHeader->data, data, count); /* We already verified this */
if(pInfo->flags & R3964_DEBUG) if(pInfo->flags & R3964_DEBUG)
{ {
......
...@@ -159,7 +159,8 @@ static ssize_t flash_read(struct file *file, char *buf, size_t size, loff_t * pp ...@@ -159,7 +159,8 @@ static ssize_t flash_read(struct file *file, char *buf, size_t size, loff_t * pp
if (ret == 0) { if (ret == 0) {
ret = count; ret = count;
*ppos += count; *ppos += count;
} } else
ret = -EFAULT;
up(&nwflash_sem); up(&nwflash_sem);
} }
return ret; return ret;
......
...@@ -163,9 +163,10 @@ int raw_ctl_ioctl(struct inode *inode, ...@@ -163,9 +163,10 @@ int raw_ctl_ioctl(struct inode *inode,
/* First, find out which raw minor we want */ /* First, find out which raw minor we want */
err = copy_from_user(&rq, (void *) arg, sizeof(rq)); if (copy_from_user(&rq, (void *) arg, sizeof(rq))) {
if (err) err = -EFAULT;
break; break;
}
minor = rq.raw_minor; minor = rq.raw_minor;
if (minor <= 0 || minor > MINORMASK) { if (minor <= 0 || minor > MINORMASK) {
...@@ -222,6 +223,8 @@ int raw_ctl_ioctl(struct inode *inode, ...@@ -222,6 +223,8 @@ int raw_ctl_ioctl(struct inode *inode,
rq.block_major = rq.block_minor = 0; rq.block_major = rq.block_minor = 0;
} }
err = copy_to_user((void *) arg, &rq, sizeof(rq)); err = copy_to_user((void *) arg, &rq, sizeof(rq));
if (err)
err = -EFAULT;
} }
break; break;
......
...@@ -1553,7 +1553,8 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp) ...@@ -1553,7 +1553,8 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp)
printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
#endif #endif
copy_from_user(&sio, sp, sizeof(struct serial_struct)); if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
return -EFAULT;
if (!capable(CAP_SYS_ADMIN)) { if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) || if ((sio.baud_base != portp->baud_base) ||
(sio.close_delay != portp->close_delay) || (sio.close_delay != portp->close_delay) ||
...@@ -2949,7 +2950,8 @@ static int stl_getbrdstats(combrd_t *bp) ...@@ -2949,7 +2950,8 @@ static int stl_getbrdstats(combrd_t *bp)
stlpanel_t *panelp; stlpanel_t *panelp;
int i; int i;
copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)); if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
return -EFAULT;
if (stl_brdstats.brd >= STL_MAXBRDS) if (stl_brdstats.brd >= STL_MAXBRDS)
return(-ENODEV); return(-ENODEV);
brdp = stl_brds[stl_brdstats.brd]; brdp = stl_brds[stl_brdstats.brd];
...@@ -2973,8 +2975,7 @@ static int stl_getbrdstats(combrd_t *bp) ...@@ -2973,8 +2975,7 @@ static int stl_getbrdstats(combrd_t *bp)
stl_brdstats.panels[i].nrports = panelp->nrports; stl_brdstats.panels[i].nrports = panelp->nrports;
} }
copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)); return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
return(0);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3017,7 +3018,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp) ...@@ -3017,7 +3018,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp)
unsigned long flags; unsigned long flags;
if (portp == (stlport_t *) NULL) { if (portp == (stlport_t *) NULL) {
copy_from_user(&stl_comstats, cp, sizeof(comstats_t)); if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
return -EFAULT;
portp = stl_getport(stl_comstats.brd, stl_comstats.panel, portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
stl_comstats.port); stl_comstats.port);
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
...@@ -3058,8 +3060,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp) ...@@ -3058,8 +3060,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp)
portp->stats.signals = (unsigned long) stl_getsignals(portp); portp->stats.signals = (unsigned long) stl_getsignals(portp);
copy_to_user(cp, &portp->stats, sizeof(comstats_t)); return copy_to_user(cp, &portp->stats,
return(0); sizeof(comstats_t)) ? -EFAULT : 0;
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3071,7 +3073,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp) ...@@ -3071,7 +3073,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t *cp)
static int stl_clrportstats(stlport_t *portp, comstats_t *cp) static int stl_clrportstats(stlport_t *portp, comstats_t *cp)
{ {
if (portp == (stlport_t *) NULL) { if (portp == (stlport_t *) NULL) {
copy_from_user(&stl_comstats, cp, sizeof(comstats_t)); if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
return -EFAULT;
portp = stl_getport(stl_comstats.brd, stl_comstats.panel, portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
stl_comstats.port); stl_comstats.port);
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
...@@ -3082,8 +3085,8 @@ static int stl_clrportstats(stlport_t *portp, comstats_t *cp) ...@@ -3082,8 +3085,8 @@ static int stl_clrportstats(stlport_t *portp, comstats_t *cp)
portp->stats.brd = portp->brdnr; portp->stats.brd = portp->brdnr;
portp->stats.panel = portp->panelnr; portp->stats.panel = portp->panelnr;
portp->stats.port = portp->portnr; portp->stats.port = portp->portnr;
copy_to_user(cp, &portp->stats, sizeof(comstats_t)); return copy_to_user(cp, &portp->stats,
return(0); sizeof(comstats_t)) ? -EFAULT : 0;
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3096,13 +3099,14 @@ static int stl_getportstruct(unsigned long arg) ...@@ -3096,13 +3099,14 @@ static int stl_getportstruct(unsigned long arg)
{ {
stlport_t *portp; stlport_t *portp;
copy_from_user(&stl_dummyport, (void *) arg, sizeof(stlport_t)); if (copy_from_user(&stl_dummyport, (void *) arg, sizeof(stlport_t)))
return -EFAULT;
portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
stl_dummyport.portnr); stl_dummyport.portnr);
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
return(-ENODEV); return(-ENODEV);
copy_to_user((void *) arg, portp, sizeof(stlport_t)); return copy_to_user((void *)arg, portp,
return(0); sizeof(stlport_t)) ? -EFAULT : 0;
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3115,14 +3119,14 @@ static int stl_getbrdstruct(unsigned long arg) ...@@ -3115,14 +3119,14 @@ static int stl_getbrdstruct(unsigned long arg)
{ {
stlbrd_t *brdp; stlbrd_t *brdp;
copy_from_user(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t)); if (copy_from_user(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t)))
return -EFAULT;
if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS)) if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
return(-ENODEV); return(-ENODEV);
brdp = stl_brds[stl_dummybrd.brdnr]; brdp = stl_brds[stl_dummybrd.brdnr];
if (brdp == (stlbrd_t *) NULL) if (brdp == (stlbrd_t *) NULL)
return(-ENODEV); return(-ENODEV);
copy_to_user((void *) arg, brdp, sizeof(stlbrd_t)); return copy_to_user((void *)arg, brdp, sizeof(stlbrd_t)) ? -EFAULT : 0;
return(0);
} }
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -1720,8 +1720,11 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, ...@@ -1720,8 +1720,11 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
Get_user (data, descr++); Get_user (data, descr++);
while (nbytes && data) { while (nbytes && data) {
for (i=0;i<nbytes;i += SX_CHUNK_SIZE) { for (i=0;i<nbytes;i += SX_CHUNK_SIZE) {
copy_from_user (tmp, (char *)data+i, if (copy_from_user(tmp, (char *)data + i,
(i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); (i + SX_CHUNK_SIZE >
nbytes) ? nbytes - i :
SX_CHUNK_SIZE))
return -EFAULT;
memcpy_toio ((char *) (board->base2 + offset + i), tmp, memcpy_toio ((char *) (board->base2 + offset + i), tmp,
(i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
} }
......
...@@ -1944,13 +1944,9 @@ static ssize_t qic02_tape_read(struct file *filp, char *buf, size_t count, ...@@ -1944,13 +1944,9 @@ static ssize_t qic02_tape_read(struct file *filp, char *buf, size_t count,
} }
/* copy buffer to user-space in one go */ /* copy buffer to user-space in one go */
if (bytes_done > 0) { if (bytes_done > 0) {
err = if (copy_to_user(buf, buffaddr, bytes_done))
copy_to_user(buf, buffaddr,
bytes_done);
if (err) {
return -EFAULT; return -EFAULT;
} }
}
#if 1 #if 1
/* Checks Ton's patch below */ /* Checks Ton's patch below */
if ((return_read_eof == NO) if ((return_read_eof == NO)
...@@ -2085,10 +2081,8 @@ static ssize_t qic02_tape_write(struct file *filp, const char *buf, ...@@ -2085,10 +2081,8 @@ static ssize_t qic02_tape_write(struct file *filp, const char *buf,
/* copy from user to DMA buffer and initiate transfer. */ /* copy from user to DMA buffer and initiate transfer. */
if (bytes_todo > 0) { if (bytes_todo > 0) {
err = copy_from_user(buffaddr, buf, bytes_todo); if (copy_from_user(buffaddr, buf, bytes_todo))
if (err) {
return -EFAULT; return -EFAULT;
}
/****************** similar problem with read() at FM could happen here at EOT. /****************** similar problem with read() at FM could happen here at EOT.
******************/ ******************/
......
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