[patch] 2.1.89 - parport_procfs bug fix

Riccardo Facchetti (fizban@tin.it)
Sun, 15 Mar 1998 16:25:14 +0100 (MET)


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