]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
nvram: Fix write beyond end condition; prove to gcc copy is safe
authorH. Peter Anvin <hpa@zytor.com>
Fri, 11 Dec 2009 23:48:23 +0000 (15:48 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 13 Aug 2010 20:50:34 +0000 (13:50 -0700)
commit a01c7800420d2c294ca403988488a635d4087a6d upstream.

In nvram_write, first of all, correctly handle the case where the file
pointer is already beyond the end; we should return EOF in that case.

Second, make the logic a bit more explicit so that gcc can statically
prove that the copy_from_user() is safe.  Once the condition of the
beyond-end filepointer is eliminated, the copy is safe but gcc can't
prove it, causing build failures for i386 allyesconfig.

Third, eliminate the entirely superfluous variable "len", and just use
the passed-in variable "count" instead.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <tip-*@git.kernel.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/char/nvram.c

index 39f6357e3b5d0a63e432cf0238cc84aba4b8d33f..1a5d40daeb8ff72e4da3bf0bfccf13a069cbd114 100644 (file)
@@ -265,10 +265,16 @@ nvram_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo
        unsigned char contents[NVRAM_BYTES];
        unsigned i = *ppos;
        unsigned char *tmp;
-       int len;
 
-       len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count;
-       if (copy_from_user(contents, buf, len))
+       if (i >= NVRAM_BYTES)
+               return 0;       /* Past EOF */
+
+       if (count > NVRAM_BYTES - i)
+               count = NVRAM_BYTES - i;
+       if (count > NVRAM_BYTES)
+               return -EFAULT; /* Can't happen, but prove it to gcc */
+
+       if (copy_from_user(contents, buf, count))
                return -EFAULT;
 
        spin_lock_irq(&rtc_lock);
@@ -276,7 +282,7 @@ nvram_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo
        if (!__nvram_check_checksum())
                goto checksum_err;
 
-       for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+       for (tmp = contents; count--; ++i, ++tmp)
                __nvram_write_byte(*tmp, i);
 
        __nvram_set_checksum();