Messages in this thread Patch in this message |  | | Date | Sun, 27 Aug 2000 19:58:54 -0300 | From | Arnaldo Carvalho de Melo <> | Subject | [PATCH] drivers/tc/zs.c: several fixes and cleanups |
| |
Hi,
Please consider applying.
- Arnaldo
--- linux-2.4.0-test7/drivers/tc/zs.c Mon Jul 10 02:30:36 2000 +++ linux-2.4.0-test7.acme/drivers/tc/zs.c Sun Aug 27 19:56:41 2000 @@ -14,6 +14,14 @@ * Keyboard and mouse are not supported right now. If you want to change this, * you might want to have a look at drivers/sbus/char/sunserial.c to see * how this might be done. HK + * + * Changes: + * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/27 + * - get rid of verify_area + * - release resource on failure on zs_init + * - get rid of panic + * - use capable(CAP_SYS_ADMIN) instead of suser + * - some other small cleanups */ #include <linux/config.h> @@ -804,7 +812,11 @@ if (from_user) { down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); + if (copy_from_user(tmp_buf, buf, c)) { + up(&tmp_buf_sem); + restore_flags(flags); + return 0; + } c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); @@ -968,7 +980,7 @@ tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; } static int set_serial_info(struct dec_serial * info, @@ -976,14 +988,12 @@ { struct serial_struct new_serial; struct dec_serial old_info; - int retval = 0; - if (!new_info) + if (!new_info || copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - copy_from_user(&new_serial,new_info,sizeof(new_serial)); old_info = *info; - if (!suser()) { + if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.baud_base != info->baud_base) || (new_serial.type != info->type) || (new_serial.close_delay != info->close_delay) || @@ -1012,8 +1022,7 @@ info->closing_wait = new_serial.closing_wait; check_and_exit: - retval = startup(info); - return retval; + return startup(info); } /* @@ -1033,8 +1042,7 @@ cli(); status = read_zsreg(info->zs_channel, 0); sti(); - put_user(status,value); - return 0; + return put_user(status,value); } static int get_modem_info(struct dec_serial *info, unsigned int *value) @@ -1050,8 +1058,7 @@ | ((control & DTR) ? TIOCM_DTR: 0) | ((status & DCD) ? TIOCM_CAR: 0) | ((status & CTS) ? 0: TIOCM_CTS); - put_user(result,value); - return 0; + return put_user(result,value); } static int set_modem_info(struct dec_serial *info, unsigned int cmd, @@ -1060,10 +1067,8 @@ int error; unsigned int arg, bits; - error = verify_area(VERIFY_READ, value, sizeof(int)); - if (error) - return error; - get_user(arg, value); + if (get_user(arg, value)) + return -EFAULT; bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); cli(); switch (cmd) { @@ -1129,41 +1134,22 @@ switch (cmd) { case TIOCMGET: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; return get_modem_info(info, (unsigned int *) arg); case TIOCMBIS: case TIOCMBIC: case TIOCMSET: return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - else - return get_lsr_info(info, (unsigned int *) arg); - + return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct dec_serial)); - if (error) - return error; - copy_from_user((struct dec_serial *) arg, - info, sizeof(struct dec_serial)); - return 0; + return copy_from_user((struct dec_serial *) arg, + info, sizeof(struct dec_serial)) ? -EFAULT : 0; default: return -ENOIOCTLCMD; @@ -1714,10 +1700,16 @@ callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; - if (tty_register_driver(&serial_driver)) - panic("Couldn't register serial driver\n"); - if (tty_register_driver(&callout_driver)) - panic("Couldn't register callout driver\n"); + i = tty_register_driver(&serial_driver); + if (i) { + printf(KERN_ERR "Couldn't register serial driver\n"); + return i; + } + i = tty_register_driver(&callout_driver); + if (i) { + printk(KERN_ERR "Couldn't register callout driver\n"); + goto cleanup_serial_driver; + } save_flags(flags); cli(); @@ -1731,9 +1723,13 @@ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ, - "SCC", &zs_soft[channel])) + "SCC", &zs_soft[channel])) { printk(KERN_ERR "decserial: can't get irq %d\n", SERIAL); + restore_flags(flags); + i = -EBUSY; + goto cleanup_channels; + } /* If console serial line, then enable interrupts. */ /* if (zs_soft[channel].is_cons) { @@ -1777,6 +1773,15 @@ restore_flags(flags); return 0; +cleanup_channels: + while (--channel >= 0) + free_irq(SERIAL, &zs_soft[channel]); + if (tty_unregister_driver(&callout_driver)) + printk("zs: failed to unregister callout driver\n"); +cleanup_serial_driver: + if (tty_unregister_driver(&serial_driver)) + printk("zs: failed to unregister serial driver\n"); + return i; } /* - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
|  |