diff options
Diffstat (limited to 'fs/compat.c')
| -rw-r--r-- | fs/compat.c | 193 | 
1 files changed, 4 insertions, 189 deletions
diff --git a/fs/compat.c b/fs/compat.c index fe40fde2911..5058345dc27 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -558,6 +558,10 @@ ssize_t compat_rw_copy_check_uvector(int type,  	}  	*ret_pointer = iov; +	ret = -EFAULT; +	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) +		goto out; +  	/*  	 * Single unix specification:  	 * We should -EINVAL if an element length is not >= 0 and fitting an @@ -1065,195 +1069,6 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,  }  #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ -static ssize_t compat_do_readv_writev(int type, struct file *file, -			       const struct compat_iovec __user *uvector, -			       unsigned long nr_segs, loff_t *pos) -{ -	compat_ssize_t tot_len; -	struct iovec iovstack[UIO_FASTIOV]; -	struct iovec *iov = iovstack; -	ssize_t ret; -	io_fn_t fn; -	iov_fn_t fnv; - -	ret = -EINVAL; -	if (!file->f_op) -		goto out; - -	ret = -EFAULT; -	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) -		goto out; - -	tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs, -					       UIO_FASTIOV, iovstack, &iov); -	if (tot_len == 0) { -		ret = 0; -		goto out; -	} - -	ret = rw_verify_area(type, file, pos, tot_len); -	if (ret < 0) -		goto out; - -	fnv = NULL; -	if (type == READ) { -		fn = file->f_op->read; -		fnv = file->f_op->aio_read; -	} else { -		fn = (io_fn_t)file->f_op->write; -		fnv = file->f_op->aio_write; -	} - -	if (fnv) -		ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, -						pos, fnv); -	else -		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); - -out: -	if (iov != iovstack) -		kfree(iov); -	if ((ret + (type == READ)) > 0) { -		if (type == READ) -			fsnotify_access(file); -		else -			fsnotify_modify(file); -	} -	return ret; -} - -static size_t compat_readv(struct file *file, -			   const struct compat_iovec __user *vec, -			   unsigned long vlen, loff_t *pos) -{ -	ssize_t ret = -EBADF; - -	if (!(file->f_mode & FMODE_READ)) -		goto out; - -	ret = -EINVAL; -	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) -		goto out; - -	ret = compat_do_readv_writev(READ, file, vec, vlen, pos); - -out: -	if (ret > 0) -		add_rchar(current, ret); -	inc_syscr(current); -	return ret; -} - -asmlinkage ssize_t -compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, -		 unsigned long vlen) -{ -	struct fd f = fdget(fd); -	ssize_t ret; -	loff_t pos; - -	if (!f.file) -		return -EBADF; -	pos = f.file->f_pos; -	ret = compat_readv(f.file, vec, vlen, &pos); -	f.file->f_pos = pos; -	fdput(f); -	return ret; -} - -asmlinkage ssize_t -compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec, -		    unsigned long vlen, loff_t pos) -{ -	struct fd f; -	ssize_t ret; - -	if (pos < 0) -		return -EINVAL; -	f = fdget(fd); -	if (!f.file) -		return -EBADF; -	ret = -ESPIPE; -	if (f.file->f_mode & FMODE_PREAD) -		ret = compat_readv(f.file, vec, vlen, &pos); -	fdput(f); -	return ret; -} - -asmlinkage ssize_t -compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, -		  unsigned long vlen, u32 pos_low, u32 pos_high) -{ -	loff_t pos = ((loff_t)pos_high << 32) | pos_low; -	return compat_sys_preadv64(fd, vec, vlen, pos); -} - -static size_t compat_writev(struct file *file, -			    const struct compat_iovec __user *vec, -			    unsigned long vlen, loff_t *pos) -{ -	ssize_t ret = -EBADF; - -	if (!(file->f_mode & FMODE_WRITE)) -		goto out; - -	ret = -EINVAL; -	if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) -		goto out; - -	ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); - -out: -	if (ret > 0) -		add_wchar(current, ret); -	inc_syscw(current); -	return ret; -} - -asmlinkage ssize_t -compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, -		  unsigned long vlen) -{ -	struct fd f = fdget(fd); -	ssize_t ret; -	loff_t pos; - -	if (!f.file) -		return -EBADF; -	pos = f.file->f_pos; -	ret = compat_writev(f.file, vec, vlen, &pos); -	f.file->f_pos = pos; -	fdput(f); -	return ret; -} - -asmlinkage ssize_t -compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec, -		     unsigned long vlen, loff_t pos) -{ -	struct fd f; -	ssize_t ret; - -	if (pos < 0) -		return -EINVAL; -	f = fdget(fd); -	if (!f.file) -		return -EBADF; -	ret = -ESPIPE; -	if (f.file->f_mode & FMODE_PWRITE) -		ret = compat_writev(f.file, vec, vlen, &pos); -	fdput(f); -	return ret; -} - -asmlinkage ssize_t -compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, -		   unsigned long vlen, u32 pos_low, u32 pos_high) -{ -	loff_t pos = ((loff_t)pos_high << 32) | pos_low; -	return compat_sys_pwritev64(fd, vec, vlen, pos); -} -  asmlinkage long  compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,  		    unsigned int nr_segs, unsigned int flags)  |