Messages in this thread Patch in this message | | | Date | Sun, 15 Mar 1998 16:25:14 +0100 (MET) | From | Riccardo Facchetti <> | Subject | [patch] 2.1.89 - parport_procfs bug fix |
| |
Hello, this is a fix for /proc/parport/?/irq handling (irq_write_proc()). When writing to it, you may end up with kernel crashes or Oopses. Mainly 2 things was wrong:
- string parsing (no checks again bad strings written to the irq file) - irq grabbing (no checks again errors returned by request_irq())
I have tested it on my machine and seems to work well. Please Linus, consider its inclusion in 2.1.90.
Ciao, Riccardo. -------------------- --- linux/drivers/misc/parport_procfs.c.orig Sat Mar 14 11:55:21 1998 +++ linux/drivers/misc/parport_procfs.c Sun Mar 15 16:05:38 1998 @@ -5,12 +5,16 @@ * Philip Blundell <philb@gnu.org> * Andrea Arcangeli <arcangeli@mbox.queen.it> * + * Bug fixes: + * Riccardo Facchetti <fizban@tin.it> + * * based on work by Grant Guenther <grant@torque.net> * and Philip Blundell */ #include <linux/stddef.h> #include <linux/tasks.h> +#include <linux/ctype.h> #include <asm/ptrace.h> #include <asm/io.h> #include <asm/dma.h> @@ -32,15 +36,26 @@ static int irq_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { - int newirq, oldirq; + int retval = -EINVAL; + int newirq; struct parport *pp = (struct parport *)data; - - if (count > 5 ) /* more than 4 digits + \n for a irq 0x?? 0?? ?? */ - return -EOVERFLOW; + struct pardevice *cad = pp->cad; + int oldirq = pp->irq; - if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) { - newirq = PARPORT_IRQ_NONE; - } else { +/* + * We can have these valid cases: + * "none" (count == 5) + * decimal number (count == 2 || count == 3) + * octal number (count == 3 || count == 4) + * hex number (count == 4 || count == 5) + * all other cases are -EINVAL + * + * -RF + */ + if (count > 5 || count == 1) + goto out; + + if (isdigit(buffer[0])) { if (buffer[0] == '0') { if (buffer[1] == 'x') newirq = simple_strtoul(&buffer[2], 0, 16); @@ -49,38 +64,52 @@ } else { newirq = simple_strtoul(buffer, 0, 10); } + } else { + if (!strncmp(buffer, "none", 4)) + newirq = PARPORT_IRQ_NONE; + else + goto out; } - if (newirq >= NR_IRQS) - return -EOVERFLOW; + if (oldirq == newirq) + goto out; + + if (pp->flags & PARPORT_FLAG_COMA) + goto out_ok; - if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) { - if (pp->cad != NULL && pp->cad->irq_func != NULL) - free_irq(pp->irq, pp->cad->private); + if (oldirq != PARPORT_IRQ_NONE) { + if (cad && cad->irq_func) + free_irq(oldirq, cad->private); else - free_irq(pp->irq, NULL); + free_irq(oldirq, NULL); } - oldirq = pp->irq; - pp->irq = newirq; - - if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) { - struct pardevice *cad = pp->cad; + if (newirq != PARPORT_IRQ_NONE) { + void (*handler)(int, void *, struct pt_regs *); - if (cad == NULL) - request_irq(pp->irq, parport_null_intr_func, - SA_INTERRUPT, pp->name, NULL); + if (cad && cad->irq_func) + handler = cad->irq_func; else - request_irq(pp->irq, cad->irq_func ? cad->irq_func : - parport_null_intr_func, SA_INTERRUPT, - cad->name, cad->private); + handler = parport_null_intr_func; + + retval = request_irq(newirq, handler, + SA_INTERRUPT, + cad ? cad->name : pp->name, + cad ? cad->private : NULL); + if (retval < 0) + goto out; } +out_ok: + pp->irq = newirq; + if (oldirq != PARPORT_IRQ_NONE && newirq == PARPORT_IRQ_NONE && - pp->cad != NULL && pp->cad->irq_func != NULL) - pp->cad->irq_func(pp->irq, pp->cad->private, NULL); + cad && cad->irq_func) + cad->irq_func(pp->irq, cad->private, NULL); - return count; + retval = count; +out: + return retval; } static int irq_read_proc(char *page, char **start, off_t off, --- linux/Documentation/parport.txt.orig Tue Dec 2 21:00:09 1997 +++ linux/Documentation/parport.txt Sat Mar 14 13:57:24 1998 @@ -93,7 +93,8 @@ port (as above). This is in a separate file to allow you to alter it by writing a new value in (IRQ number - or "none"). + in octal, decimal or hexadecimal, or + the string "none"). Device drivers ==============
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |