[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;
- printk changes,
Alfred M. Szmidt <=