From 8f0b4f678e7f82e415413643a22604925929a157 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Dec 2009 15:48:23 -0800 Subject: nvram: Fix write beyond end condition; prove to gcc copy is safe 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 Cc: Arjan van de Ven Cc: Andrew Morton Cc: Wim Van Sebroeck Cc: Frederic Weisbecker LKML-Reference: Cc: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman --- drivers/char/nvram.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 39f6357e3b5d..1a5d40daeb8f 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -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(); -- cgit v1.2.3