From 6a029a90f5b93e2b50bcbbaef05ef91fa0c1d6b3 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@parcelfarce.linux.theplanet.co.uk> Date: Sat, 27 Aug 2005 06:48:15 +0100 Subject: [PATCH] mmaper_kern.c fixes [buffer overruns] - copy_from_user() can fail; ->write() must check its return value. - severe buffer overruns both in ->read() and ->write() - lseek to the end (i.e. to mmapper_size) and if (count + *ppos > mmapper_size) count = count + *ppos - mmapper_size; will do absolutely nothing. Then it will call copy_to_user(buf,&v_buf[*ppos],count); with obvious results (similar for ->write()). Fixed by turning read to simple_read_from_buffer() and by doing normal limiting of count in ->write(). - gratitious lock_kernel() in ->mmap() - it's useless there. - lots of gratuitous includes. Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org> --- arch/um/drivers/mmapper_kern.c | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index a37a5ac13c22..022f67bb6873 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -9,19 +9,11 @@ * */ -#include <linux/types.h> -#include <linux/kdev_t.h> -#include <linux/time.h> -#include <linux/devfs_fs_kernel.h> +#include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/miscdevice.h> #include <asm/uaccess.h> -#include <asm/irq.h> -#include <asm/pgtable.h> #include "mem_user.h" #include "user_util.h" @@ -31,35 +23,22 @@ static unsigned long p_buf = 0; static char *v_buf = NULL; static ssize_t -mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos) +mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - if(*ppos > mmapper_size) - return -EINVAL; - - if(count + *ppos > mmapper_size) - count = count + *ppos - mmapper_size; - - if(count < 0) - return -EINVAL; - - copy_to_user(buf,&v_buf[*ppos],count); - - return count; + return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size); } static ssize_t -mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if(*ppos > mmapper_size) + if (*ppos > mmapper_size) return -EINVAL; - if(count + *ppos > mmapper_size) - count = count + *ppos - mmapper_size; - - if(count < 0) - return -EINVAL; + if (count > mmapper_size - *ppos) + count = mmapper_size - *ppos; - copy_from_user(&v_buf[*ppos],buf,count); + if (copy_from_user(&v_buf[*ppos], buf, count)) + return -EFAULT; return count; } @@ -77,7 +56,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma) int ret = -EINVAL; int size; - lock_kernel(); if (vma->vm_pgoff != 0) goto out; @@ -92,7 +70,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma) goto out; ret = 0; out: - unlock_kernel(); return ret; } -- cgit v1.2.3