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