From 8cbbcb8ec470107dfca0a5562543cf4854e67a05 Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Thu, 29 Apr 1999 17:29:11 +0000 Subject: [PATCH] Nasty buffer overflow in i2c-proc.c solved. This one was not nice at all. When /proc/bus/i2c-* is read, information is put into a kernel buffer, which was declared to be the same size as the final user-space buffer into which it should be copied. Information was copied into the kernel buffer line by line (using sprintf). If the buffer is smaller than the whole /proc/bus/i2c-*, only part of the file was copied. But if the buffer did not break on a line-break, the sprintf wrote beyond the kernel buffer. With devastating results. Solution: make the kernel buffer a little longer, so that a single additional line would fit into it. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@431 7894878c-1315-0410-8ee3-d5d059ff63e0 --- kernel/i2c-proc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/i2c-proc.c b/kernel/i2c-proc.c index 627fc26a..b8dff185 100644 --- a/kernel/i2c-proc.c +++ b/kernel/i2c-proc.c @@ -259,10 +259,11 @@ int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused) #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ { int i; - len = 0; - for (i = 0; i < I2C_ADAP_MAX; i++) + int nr = 0; + /* Note that it is safe to write a `little' beyond len. Yes, really. */ + for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++) if (i2cproc_adapters[i]) - len += sprintf(buf+len, "i2c-%d\t%s\t%-32s\t%-32s\n", + nr += sprintf(buf+nr, "i2c-%d\t%s\t%-32s\t%-32s\n", i2c_adapter_id(i2cproc_adapters[i]), i2c_is_smbus_adapter(i2cproc_adapters[i])?"smbus": #ifdef DEBUG @@ -271,7 +272,7 @@ int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused) "i2c", i2cproc_adapters[i]->name, i2cproc_adapters[i]->algo->name); - return len; + return nr; } /* This function generates the output for /proc/bus/i2c-? */ @@ -295,7 +296,9 @@ int i2cproc_bus_read(struct inode * inode, struct file * file,char * buf, count = 4000; for (i = 0; i < I2C_ADAP_MAX; i++) if (i2cproc_inodes[i] == inode->i_ino) { - if (! (kbuf = kmalloc(count,GFP_KERNEL))) + /* We need a bit of slack in the kernel buffer; this makes the + sprintf safe. */ + if (! (kbuf = kmalloc(count + 80,GFP_KERNEL))) return -ENOMEM; for (j = 0; j < I2C_CLIENT_MAX; j++) if ((client = i2cproc_adapters[i]->clients[j]))