User: Password:
|
|
Subscribe / Log in / New account

Make read/write always do the full "access_ok()" tests.

From:  Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To:  bk-commits-head@vger.kernel.org
Subject:  Make read/write always do the full "access_ok()" tests.
Date:  Thu, 03 Feb 2005 17:37:45 +0000
Archive-link:  Article, Thread

ChangeSet 1.2040.3.8, 2005/02/03 09:37:45-08:00, torvalds@ppc970.osdl.org

	Make read/write always do the full "access_ok()" tests.
	
	The actual user copy will do them too, but only for the
	range that ends up being actually copied. That hides
	bugs when the range has been clamped by file size or other
	issues.



 read_write.c |   13 +++++++++++++
 1 files changed, 13 insertions(+)


diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	2005-02-03 11:12:19 -08:00
+++ b/fs/read_write.c	2005-02-03 11:12:19 -08:00
@@ -220,6 +220,8 @@
 		return -EBADF;
 	if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
 		return -EINVAL;
+	if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
+		return -EFAULT;
 
 	ret = rw_verify_area(READ, file, pos, count);
 	if (!ret) {
@@ -266,6 +268,8 @@
 		return -EBADF;
 	if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
 		return -EINVAL;
+	if (unlikely(!access_ok(VERIFY_READ, buf, count)))
+		return -EFAULT;
 
 	ret = rw_verify_area(WRITE, file, pos, count);
 	if (!ret) {
@@ -397,6 +401,9 @@
 
 EXPORT_SYMBOL(iov_shorten);
 
+/* A write operation does a read from user space and vice versa */
+#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
+
 static ssize_t do_readv_writev(int type, struct file *file,
 			       const struct iovec __user * uvector,
 			       unsigned long nr_segs, loff_t *pos)
@@ -450,8 +457,11 @@
 	tot_len = 0;
 	ret = -EINVAL;
 	for (seg = 0; seg < nr_segs; seg++) {
+		void __user *buf = iov[seg].iov_base;
 		ssize_t len = (ssize_t)iov[seg].iov_len;
 
+		if (unlikely(!access_ok(vrfy_dir(type), buf, len)))
+			goto Efault;
 		if (len < 0)	/* size_t not fitting an ssize_t .. */
 			goto out;
 		tot_len += len;
@@ -510,6 +520,9 @@
 		dnotify_parent(file->f_dentry,
 				(type == READ) ? DN_ACCESS : DN_MODIFY);
 	return ret;
+Efault:
+	ret = -EFAULT;
+	goto out;
 }
 
 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,


Copyright © 2005, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds