aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-12-11 18:48:23 -0500
committerH. Peter Anvin <hpa@zytor.com>2009-12-11 18:48:23 -0500
commita01c7800420d2c294ca403988488a635d4087a6d (patch)
treea0a5eeb436a297dffead2dfbccbb0ad3013aa7d1 /drivers/char
parentb925585039cf39275c2e0e57512e5df27fa73aad (diff)
nvram: Fix write beyond end condition; prove to gcc copy is safe
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>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/nvram.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 4008e2ce73c1..fdbcc9fd6d31 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -264,10 +264,16 @@ static ssize_t nvram_write(struct file *file, const char __user *buf,
264 unsigned char contents[NVRAM_BYTES]; 264 unsigned char contents[NVRAM_BYTES];
265 unsigned i = *ppos; 265 unsigned i = *ppos;
266 unsigned char *tmp; 266 unsigned char *tmp;
267 int len;
268 267
269 len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count; 268 if (i >= NVRAM_BYTES)
270 if (copy_from_user(contents, buf, len)) 269 return 0; /* Past EOF */
270
271 if (count > NVRAM_BYTES - i)
272 count = NVRAM_BYTES - i;
273 if (count > NVRAM_BYTES)
274 return -EFAULT; /* Can't happen, but prove it to gcc */
275
276 if (copy_from_user(contents, buf, count))
271 return -EFAULT; 277 return -EFAULT;
272 278
273 spin_lock_irq(&rtc_lock); 279 spin_lock_irq(&rtc_lock);
@@ -275,7 +281,7 @@ static ssize_t nvram_write(struct file *file, const char __user *buf,
275 if (!__nvram_check_checksum()) 281 if (!__nvram_check_checksum())
276 goto checksum_err; 282 goto checksum_err;
277 283
278 for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) 284 for (tmp = contents; count--; ++i, ++tmp)
279 __nvram_write_byte(*tmp, i); 285 __nvram_write_byte(*tmp, i);
280 286
281 __nvram_set_checksum(); 287 __nvram_set_checksum();