lkml.org 
[lkml]   [1998]   [Mar]   [15]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateSun, 15 Mar 1998 16:25:14 +0100 (MET)
FromRiccardo 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

\
 
 \ /
  Last update: 2005-03-22 12:41    [from the cache]
©2003-2008