Patches for printk() and panic()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
    I found some bugs in kernel/printk.c file. To test printk() and
panic(), I inserted the next code in init_task(), after mounting the
root filesystem.

    printk("Printing 1234 using %%d, %d\n", 1234);
    printk("Printing -1234 using %%d, %d\n", -1234);
    printk("Printing 1234 using %%8d, %8d\n", 1234);
    printk("Printing -1234 using %%8d, %8d\n", -1234);
    printk("Printing 1234 using %%08d, %08d\n", 1234);
    printk("Printing -1234 using %%08d, %08d\n", -1234);
    panic("Now testing panic with 2 int parameters: %d, %d\n", 22, 33);

 After booting ELKS with the original printk.c, the console shows:

Printing 1234 using %d, 1234
Printing -1234 using %d, -1234
Printing 1234 using %8d,     1234
Printing -1234 using %8d, -    1234
Printing 1234 using %08d, 00001234
Printing -1234 using %08d, -00001234

panic: Now testing panic with 2 int parameters: 22, 1

apparent call stack:
Line: Addr    Parameters
~~~~: ~~~~    ~~~~~~~~~~
   0: 012D => 0000 0000 0000 0000 0000 0000 0000

SYSTEM LOCKED - Press CTRL-ALT-DEL to reboot:

  With format %8d and %08d and negative numbers, the resulting field
width is 9 instead of 8. With format %8d the sign is separated from
the number. In the function panic(), only the first parameter is
printed correctly, in the place of the second  parameter prints garbage.
Only one stack frame is printed, instead of the 9 frames that
the code suggest.

 After booting ELKS with the modified printk.c, the console shows:

Printing 1234 using %d, 1234
Printing -1234 using %d, -1234
Printing 1234 using %8d,     1234
Printing -1234 using %8d,    -1234
Printing 1234 using %08d, 00001234
Printing -1234 using %08d, -0001234

panic: Now testing panic with 2 int parameters: 22, 1

apparent call stack:
Line: Addr    Parameters
~~~~: ~~~~    ~~~~~~~~~~
   0: 012D => 0000 0000 0000 0000 0000 0000 0000
   1: 0000 => 23E8 00AD 9F40 2CD8 E76C 0092 3FF2
   2: 009E => E5E0 1F20 E76C 0000 0000 0001 0000
   3: 001E => 0000 0000 0000 0000 0000 0000 0000
   4: 0000 => 0000 0000 0000 0000 0000 0000 0000
   5: 0000 => 0000 0000 0000 0000 0000 0000 0000
   6: 0000 => 0000 0000 0000 0000 0000 0000 0000
   7: 0000 => 0000 0000 0000 0000 0000 0000 0000
   8: 0000 => 0000 0000 0000 0000 0000 0000 0000

SYSTEM LOCKED - Press CTRL-ALT-DEL to reboot:

Negative numbers are now printed correctly. With panic(),
9 stack frames are printed. Still, only the first parameter
is printed correctly. Code size is reduced in 32 bytes.

The patch to fix printk() and panic() bugs follows:
diff -Nurb elks.orig/kernel/printk.c elks/kernel/printk.c
--- elks.orig/kernel/printk.c	2004-05-31 08:49:25.000000000 -0500
+++ elks/kernel/printk.c	2012-01-16 09:46:18.000000000 -0600
@@ -25,18 +25,14 @@
  *	MTK:	Sep 97 - Misc hacks to shrink generated code
  */

-#include <linuxmt/fcntl.h>
-#include <linuxmt/mm.h>
-#include <linuxmt/sched.h>
-#include <linuxmt/types.h>
-
 #include <arch/segment.h>
+#include <linuxmt/mm.h>

 /*
  *	Just to make it work for now
  */

-extern void con_charout();
+extern void con_charout(char);

 static void con_write(register char *buf, int len)
 {
@@ -48,11 +44,10 @@

     static char colour[8] = { 27, '[', '3', '0', ';', '4', '0', 'm' };

-    p = colour;
-
-    if (++(p[3]) == '8')
-	p[3] = '1';
+    if (++(colour[3]) == '8')
+	colour[3] = '1';

+    p = colour;
     do
 	con_charout(*p);
     while (*p++ != 'm');
@@ -81,42 +76,51 @@
 static void numout(char *ptr, int len, int width, int base, int useSign,
 		   int Upper, int Zero)
 {
-    long int vs;
     unsigned long int v;
-    register char *bp, *bp2;
-    char buf[32];
-
-    if (width > 31)			/* Error-check width specified */
-	width = 31;
+    register char *bp;
+    char buf[12];

-    bp = bp2 = buf + 31;
+    if (width > sizeof(buf))		/* Error-check width specified */
+	width = sizeof(buf);

-    if (useSign) {
-	vs = (len == 2) ? *((short *) ptr) : *((long *) ptr);
-	if (vs < 0) {
-	    v = - vs;
-	    *bp = '-';
-	    con_write(bp, 1);
-	} else
-	    v = vs;
-    } else
 	v = (len == 2) ? *((unsigned short *) ptr) : *((unsigned long *) ptr);
+    if (useSign) {
+	if (len == 2)
+	    v = ((long)(*((short *) ptr)));
+	if ((long)v < 0)
+	    v = (-(long)v);
+	else
+	    useSign = 0;
+    }
+
+    bp = buf + sizeof(buf);

-    *bp = 0;
+    {
+	register char *bp2;
+
+	bp2 = Upper ? hex_string : hex_lower;
     do {
-	if (Upper)
-	    *--bp = hex_string[v % base]; 	/* Store digit */
-	else
-	    *--bp = hex_lower[v % base]; 	/* Store digit */
-    } while ((v /= base) && (bp > buf));
+	    *--bp = *(bp2 + (v % base));	/* Store digit */
+	} while ((v /= base));
+    }
+
+    if (useSign && !Zero)
+	*--bp = '-';

-    while (bp2 - bp < width)			/* Process width */
+    width -= buf - bp + sizeof(buf);
+    while (--width >= 0)			/* Process width */
 	if (Zero)
 	    *--bp = '0';
 	else
 	    *--bp = ' ';

-    con_write(bp, buf - bp + sizeof(buf) - 1);
+    if (useSign && Zero) {
+	if (*bp != '0')
+	    bp--;
+	*bp = '-';
+    }
+
+    con_write(bp, buf + sizeof(buf) - bp);
 }

 void printk(register char *fmt,int a1)
@@ -180,7 +184,7 @@
 		    con_write(cp++, 1);
 		    width--;
 		}
-		while (width-- > 0)
+		while (--width >= 0)
 		    con_write(" ", 1);
 		break;
 	    case 't':
@@ -191,11 +195,11 @@
 		    cp++;
 		    width--;
 		}
-		while (width-- > 0)
+		while (--width >= 0)
 		    con_write(" ", 1);
 		break;
 	    case 'c':
-		while (width-- > 1)
+		while (--width >= 1)
 		    con_write(" ", 1);
 		con_write(p, 1);
 		p += 2;
@@ -224,7 +228,7 @@
 	for (j = 2; j <= 8; j++)
 	    printk(" %04X", bp[j]);
 	printk("\n");
-    } while (++i > 9);
+    } while (++i < 9);

     /* Lock up with infinite loop */

Regards,

Juan
--
To unsubscribe from this list: send the line "unsubscribe linux-8086" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel]     [Linux ia64]     [DCCP]     [Linux for ARM]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux