bug-hurd
[Top][All Lists]
Advanced

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

printk changes


From: Alfred M. Szmidt
Subject: printk changes
Date: Fri, 03 Dec 2004 10:19:57 +0100

Roland, the following looks OK to me.  OK to commit?

(I'm assuming that Neal tested it, but I'll test it a bit before
commit as always)

Summary:  printk may cause buffer overruns

Original Submission: The implementation of printk in
linux/dev/kernel/printk.c assumes that the formatted string is less
than sizeof (buf) - 3 (BUF being a statically allocated string of 2048
bytes). Code in Linux violates this assumption.  For instance,
linux/src/drivers/pci/pci.c:pci_init which prints out the pci bus
topography if debugging is enabled. I looked at writing a
linux_vsnprintf to replace the linux_vsprintf, however, the code is a
mess and the Mach printf code is much easier to work with
(kern/printf.c).  Hence, I modified that.

Thanks.

2004-09-08  Neal H. Walfield  <neal@cs.uml.edu>

        * linux/dev/kernel/printk.c: Include <kern/assert.h>.
        (printk): Use vsnprintf, not linux_vsprintf to avoid buffer
        overruns.

        * kern/printf.c (struct vsnprintf_cookie): New structure.
        (snputc): New function.
        (vsnprintf): Likewise.

Index: linux/dev/kernel/printk.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/linux/dev/kernel/Attic/printk.c,v
retrieving revision 1.1
diff -u -p -r1.1 printk.c
--- linux/dev/kernel/printk.c   26 Apr 1999 05:49:36 -0000      1.1
+++ linux/dev/kernel/printk.c   8 Sep 2004 10:29:05 -0000
@@ -26,6 +26,7 @@
 #define MACH_INCLUDE
 #include <stdarg.h>
 #include <asm/system.h>
+#include <kern/assert.h>
 
 static char buf[2048];
 
@@ -40,14 +41,14 @@ printk (char *fmt, ...)
   va_list args;
   int n, flags;
   extern void cnputc ();
-  extern int linux_vsprintf (char *buf, char *fmt,...);
   char *p, *msg, *buf_end;
   static int msg_level = -1;
   
   save_flags (flags);
   cli ();
   va_start (args, fmt);
-  n = linux_vsprintf (buf + 3, fmt, args);
+  n = vsnprintf (buf + 3, sizeof (buf) - 3, fmt, args);
+  assert (n <= sizeof (buf) - 3);
   buf_end = buf + 3 + n;
   va_end (args);
   for (p = buf + 3; p < buf_end; p++)
Index: kern/printf.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/kern/Attic/printf.c,v
retrieving revision 1.2
diff -u -p -r1.2 printf.c
--- kern/printf.c       23 Jul 2000 00:34:12 -0000      1.2
+++ kern/printf.c       8 Sep 2004 10:29:06 -0000
@@ -579,6 +579,34 @@ sprintf(char *buf, const char *fmt, ...)
        return (buf - start);
 }
 
+struct vsnprintf_cookie
+{
+  char *buf;
+  int index;
+  int max_len;
+};
+
+static void
+snputc(char c, vm_offset_t arg)
+{
+  struct vsnprintf_cookie *cookie = (void *) arg;
+
+  if (cookie->index < cookie->max_len)
+    cookie->buf[cookie->index ++] = c;
+}
+
+int
+vsnprintf(char *buf, int size, const char *fmt, va_list args)
+{
+  struct vsnprintf_cookie cookie
+    = { .buf = buf, .index = 0, .max_len = size };
+
+  _doprnt (fmt, &args, snputc, 16, (vm_offset_t)&cookie);
+  cookie.buf[cookie.index] = '\0';
+
+  return cookie.index;
+}
+
 
 void safe_gets(str, maxlen)
        char *str;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]