[PATCH] drivers/tc/zs.c: several fixes and cleanups

From: Arnaldo Carvalho de Melo (acme@conectiva.com.br)
Date: Sun Aug 27 2000 - 17:58:54 EST


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/



This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:20 EST