linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* clean up kernel_{read,write} & friends v4
@ 2020-06-15 12:12 Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 01/13] cachefiles: switch to kernel_write Christoph Hellwig
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

Hi Al,

this series fixes a few issues and cleans up the helpers that read from
or write to kernel space buffers, and ensures that we don't change the
address limit if we are using the ->read_iter and ->write_iter methods
that don't need the changed address limit.

I did not add your suggested comments on the instances using
uaccess_kernel as all of them already have comments.  If you have
anything better in mind feel free to throw in additional comments.


Changes since v3:
 - keep call_read_iter/call_write_iter for now
 - don't modify an existing long line
 - update a change log

Changes since v2:
 - picked up a few ACKs

Changes since v1:
 - __kernel_write must not take sb_writers
 - unexport __kernel_write

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/13] cachefiles: switch to kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 02/13] autofs: " Christoph Hellwig
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

__kernel_write doesn't take a sb_writers references, which we need here.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Howells <dhowells@redhat.com>
---
 fs/cachefiles/rdwr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index e7726f5f1241c2..3080cda9e82457 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -937,7 +937,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
 	}
 
 	data = kmap(page);
-	ret = __kernel_write(file, data, len, &pos);
+	ret = kernel_write(file, data, len, &pos);
 	kunmap(page);
 	fput(file);
 	if (ret != len)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 02/13] autofs: switch to kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 01/13] cachefiles: switch to kernel_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 03/13] bpfilter: " Christoph Hellwig
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

While pipes don't really need sb_writers projection, __kernel_write is an
interface better kept private, and the additional rw_verify_area does not
hurt here.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/waitq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index b04c528b19d342..74c886f7c51cbe 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -53,7 +53,7 @@ static int autofs_write(struct autofs_sb_info *sbi,
 
 	mutex_lock(&sbi->pipe_mutex);
 	while (bytes) {
-		wr = __kernel_write(file, data, bytes, &file->f_pos);
+		wr = kernel_write(file, data, bytes, &file->f_pos);
 		if (wr <= 0)
 			break;
 		data += wr;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 03/13] bpfilter: switch to kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 01/13] cachefiles: switch to kernel_write Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 02/13] autofs: " Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 04/13] fs: unexport __kernel_write Christoph Hellwig
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

While pipes don't really need sb_writers projection, __kernel_write is an
interface better kept private, and the additional rw_verify_area does not
hurt here.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 net/bpfilter/bpfilter_kern.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c
index c0f0990f30b604..1905e01c3aa9a7 100644
--- a/net/bpfilter/bpfilter_kern.c
+++ b/net/bpfilter/bpfilter_kern.c
@@ -50,7 +50,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
 	req.len = optlen;
 	if (!bpfilter_ops.info.pid)
 		goto out;
-	n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
+	n = kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
 			   &pos);
 	if (n != sizeof(req)) {
 		pr_err("write fail %zd\n", n);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 04/13] fs: unexport __kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (2 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 03/13] bpfilter: " Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write Christoph Hellwig
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

This is a very special interface that skips sb_writes protection, and not
used by modules anymore.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index bbfa9b12b15eb7..2c601d853ff3d8 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -522,7 +522,6 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 	inc_syscw(current);
 	return ret;
 }
-EXPORT_SYMBOL(__kernel_write);
 
 ssize_t kernel_write(struct file *file, const void *buf, size_t count,
 			    loff_t *pos)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (3 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 04/13] fs: unexport __kernel_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:34   ` Matthew Wilcox
  2020-06-15 16:39   ` Linus Torvalds
  2020-06-15 12:12 ` [PATCH 06/13] fs: implement kernel_write using __kernel_write Christoph Hellwig
                   ` (7 subsequent siblings)
  12 siblings, 2 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

We still need to check if the fѕ is open write, even for the low-level
helper.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/read_write.c b/fs/read_write.c
index 2c601d853ff3d8..76be155ad98242 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -505,6 +505,8 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 	const char __user *p;
 	ssize_t ret;
 
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EBADF;
 	if (!(file->f_mode & FMODE_CAN_WRITE))
 		return -EINVAL;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 06/13] fs: implement kernel_write using __kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (4 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 07/13] fs: remove __vfs_write Christoph Hellwig
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

Consolidate the two in-kernel write helpers to make upcoming changes
easier.  The only difference are the missing call to rw_verify_area
in kernel_write, and an access_ok check that doesn't make sense for
kernel buffers to start with.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 76be155ad98242..9d50d3cec017d8 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -499,6 +499,7 @@ static ssize_t __vfs_write(struct file *file, const char __user *p,
 		return -EINVAL;
 }
 
+/* caller is responsible for file_start_write/file_end_write */
 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
 {
 	mm_segment_t old_fs;
@@ -528,16 +529,16 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 ssize_t kernel_write(struct file *file, const void *buf, size_t count,
 			    loff_t *pos)
 {
-	mm_segment_t old_fs;
-	ssize_t res;
+	ssize_t ret;
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	/* The cast to a user pointer is valid due to the set_fs() */
-	res = vfs_write(file, (__force const char __user *)buf, count, pos);
-	set_fs(old_fs);
+	ret = rw_verify_area(WRITE, file, pos, count);
+	if (ret)
+		return ret;
 
-	return res;
+	file_start_write(file);
+	ret =  __kernel_write(file, buf, count, pos);
+	file_end_write(file);
+	return ret;
 }
 EXPORT_SYMBOL(kernel_write);
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 07/13] fs: remove __vfs_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (5 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 06/13] fs: implement kernel_write using __kernel_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 08/13] fs: don't change the address limit for ->write_iter in __kernel_write Christoph Hellwig
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

Fold it into the two callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 46 ++++++++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 9d50d3cec017d8..f81e15c95f576c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -488,17 +488,6 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
 	return ret;
 }
 
-static ssize_t __vfs_write(struct file *file, const char __user *p,
-			   size_t count, loff_t *pos)
-{
-	if (file->f_op->write)
-		return file->f_op->write(file, p, count, pos);
-	else if (file->f_op->write_iter)
-		return new_sync_write(file, p, count, pos);
-	else
-		return -EINVAL;
-}
-
 /* caller is responsible for file_start_write/file_end_write */
 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
 {
@@ -516,7 +505,12 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 	p = (__force const char __user *)buf;
 	if (count > MAX_RW_COUNT)
 		count =  MAX_RW_COUNT;
-	ret = __vfs_write(file, p, count, pos);
+	if (file->f_op->write)
+		ret = file->f_op->write(file, p, count, pos);
+	else if (file->f_op->write_iter)
+		ret = new_sync_write(file, p, count, pos);
+	else
+		ret = -EINVAL;
 	set_fs(old_fs);
 	if (ret > 0) {
 		fsnotify_modify(file);
@@ -554,19 +548,23 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
 		return -EFAULT;
 
 	ret = rw_verify_area(WRITE, file, pos, count);
-	if (!ret) {
-		if (count > MAX_RW_COUNT)
-			count =  MAX_RW_COUNT;
-		file_start_write(file);
-		ret = __vfs_write(file, buf, count, pos);
-		if (ret > 0) {
-			fsnotify_modify(file);
-			add_wchar(current, ret);
-		}
-		inc_syscw(current);
-		file_end_write(file);
+	if (ret)
+		return ret;
+	if (count > MAX_RW_COUNT)
+		count =  MAX_RW_COUNT;
+	file_start_write(file);
+	if (file->f_op->write)
+		ret = file->f_op->write(file, buf, count, pos);
+	else if (file->f_op->write_iter)
+		ret = new_sync_write(file, buf, count, pos);
+	else
+		ret = -EINVAL;
+	if (ret > 0) {
+		fsnotify_modify(file);
+		add_wchar(current, ret);
 	}
-
+	inc_syscw(current);
+	file_end_write(file);
 	return ret;
 }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 08/13] fs: don't change the address limit for ->write_iter in __kernel_write
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (6 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 07/13] fs: remove __vfs_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 09/13] fs: add a __kernel_read helper Christoph Hellwig
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

If we write to a file that implements ->write_iter there is no need
to change the address limit if we send a kvec down.  Implement that
case, and prefer it over using plain ->write with a changed address
limit if available.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index f81e15c95f576c..4fb7966f023526 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -491,8 +491,6 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
 /* caller is responsible for file_start_write/file_end_write */
 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
 {
-	mm_segment_t old_fs;
-	const char __user *p;
 	ssize_t ret;
 
 	if (!(file->f_mode & FMODE_WRITE))
@@ -500,18 +498,29 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 	if (!(file->f_mode & FMODE_CAN_WRITE))
 		return -EINVAL;
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	p = (__force const char __user *)buf;
 	if (count > MAX_RW_COUNT)
 		count =  MAX_RW_COUNT;
-	if (file->f_op->write)
-		ret = file->f_op->write(file, p, count, pos);
-	else if (file->f_op->write_iter)
-		ret = new_sync_write(file, p, count, pos);
-	else
+	if (file->f_op->write_iter) {
+		struct kvec iov = { .iov_base = (void *)buf, .iov_len = count };
+		struct kiocb kiocb;
+		struct iov_iter iter;
+
+		init_sync_kiocb(&kiocb, file);
+		kiocb.ki_pos = *pos;
+		iov_iter_kvec(&iter, WRITE, &iov, 1, count);
+		ret = file->f_op->write_iter(&kiocb, &iter);
+		if (ret > 0)
+			*pos = kiocb.ki_pos;
+	} else if (file->f_op->write) {
+		mm_segment_t old_fs = get_fs();
+
+		set_fs(KERNEL_DS);
+		ret = file->f_op->write(file, (__force const char __user *)buf,
+				count, pos);
+		set_fs(old_fs);
+	} else {
 		ret = -EINVAL;
-	set_fs(old_fs);
+	}
 	if (ret > 0) {
 		fsnotify_modify(file);
 		add_wchar(current, ret);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 09/13] fs: add a __kernel_read helper
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (7 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 08/13] fs: don't change the address limit for ->write_iter in __kernel_write Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 10/13] integrity/ima: switch to using __kernel_read Christoph Hellwig
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

This is the counterpart to __kernel_write, and skip the rw_verify_area
call compared to kernel_read.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c    | 21 +++++++++++++++++++++
 include/linux/fs.h |  1 +
 2 files changed, 22 insertions(+)

diff --git a/fs/read_write.c b/fs/read_write.c
index 4fb7966f023526..3364fdfc2982b4 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -430,6 +430,27 @@ ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
 		return -EINVAL;
 }
 
+ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
+{
+	mm_segment_t old_fs = get_fs();
+	ssize_t ret;
+
+	if (!(file->f_mode & FMODE_CAN_READ))
+		return -EINVAL;
+
+	if (count > MAX_RW_COUNT)
+		count =  MAX_RW_COUNT;
+	set_fs(KERNEL_DS);
+	ret = __vfs_read(file, (void __user *)buf, count, pos);
+	set_fs(old_fs);
+	if (ret > 0) {
+		fsnotify_access(file);
+		add_rchar(current, ret);
+	}
+	inc_syscr(current);
+	return ret;
+}
+
 ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
 	mm_segment_t old_fs;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6c4ab4dc1cd718..21613bf1b49690 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3035,6 +3035,7 @@ extern int kernel_read_file_from_path_initns(const char *, void **, loff_t *, lo
 extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
 				    enum kernel_read_file_id);
 extern ssize_t kernel_read(struct file *, void *, size_t, loff_t *);
+ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
 extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *);
 extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 10/13] integrity/ima: switch to using __kernel_read
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (8 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 09/13] fs: add a __kernel_read helper Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 16:46   ` Linus Torvalds
  2020-06-15 12:12 ` [PATCH 11/13] fs: implement kernel_read " Christoph Hellwig
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

__kernel_read has a bunch of additional sanity checks, and this moves
the set_fs out of non-core code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 security/integrity/iint.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index e12c4900510f60..1d20003243c3fb 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -188,19 +188,7 @@ DEFINE_LSM(integrity) = {
 int integrity_kernel_read(struct file *file, loff_t offset,
 			  void *addr, unsigned long count)
 {
-	mm_segment_t old_fs;
-	char __user *buf = (char __user *)addr;
-	ssize_t ret;
-
-	if (!(file->f_mode & FMODE_READ))
-		return -EBADF;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = __vfs_read(file, buf, count, &offset);
-	set_fs(old_fs);
-
-	return ret;
+	return __kernel_read(file, addr, count, &offset);
 }
 
 /*
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 11/13] fs: implement kernel_read using __kernel_read
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (9 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 10/13] integrity/ima: switch to using __kernel_read Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 12/13] fs: remove __vfs_read Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 13/13] fs: don't change the address limit for ->read_iter in __kernel_read Christoph Hellwig
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

Consolidate the two in-kernel read helpers to make upcoming changes
easier.  The only difference are the missing call to rw_verify_area
in kernel_read, and an access_ok check that doesn't make sense for
kernel buffers to start with.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 3364fdfc2982b4..e1c471982d6213 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -453,15 +453,12 @@ ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 
 ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
-	mm_segment_t old_fs;
-	ssize_t result;
+	ssize_t ret;
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	/* The cast to a user pointer is valid due to the set_fs() */
-	result = vfs_read(file, (void __user *)buf, count, pos);
-	set_fs(old_fs);
-	return result;
+	ret = rw_verify_area(READ, file, pos, count);
+	if (ret)
+		return ret;
+	return __kernel_read(file, buf, count, pos);
 }
 EXPORT_SYMBOL(kernel_read);
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 12/13] fs: remove __vfs_read
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (10 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 11/13] fs: implement kernel_read " Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  2020-06-15 12:12 ` [PATCH 13/13] fs: don't change the address limit for ->read_iter in __kernel_read Christoph Hellwig
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

Fold it into the two callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c    | 43 +++++++++++++++++++++----------------------
 include/linux/fs.h |  1 -
 2 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index e1c471982d6213..1d43da8554dc0d 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -419,17 +419,6 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
 	return ret;
 }
 
-ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
-		   loff_t *pos)
-{
-	if (file->f_op->read)
-		return file->f_op->read(file, buf, count, pos);
-	else if (file->f_op->read_iter)
-		return new_sync_read(file, buf, count, pos);
-	else
-		return -EINVAL;
-}
-
 ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
 	mm_segment_t old_fs = get_fs();
@@ -441,7 +430,12 @@ ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 	if (count > MAX_RW_COUNT)
 		count =  MAX_RW_COUNT;
 	set_fs(KERNEL_DS);
-	ret = __vfs_read(file, (void __user *)buf, count, pos);
+	if (file->f_op->read)
+		ret = file->f_op->read(file, (void __user *)buf, count, pos);
+	else if (file->f_op->read_iter)
+		ret = new_sync_read(file, (void __user *)buf, count, pos);
+	else
+		ret = -EINVAL;
 	set_fs(old_fs);
 	if (ret > 0) {
 		fsnotify_access(file);
@@ -474,17 +468,22 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
 		return -EFAULT;
 
 	ret = rw_verify_area(READ, file, pos, count);
-	if (!ret) {
-		if (count > MAX_RW_COUNT)
-			count =  MAX_RW_COUNT;
-		ret = __vfs_read(file, buf, count, pos);
-		if (ret > 0) {
-			fsnotify_access(file);
-			add_rchar(current, ret);
-		}
-		inc_syscr(current);
-	}
+	if (ret)
+		return ret;
+	if (count > MAX_RW_COUNT)
+		count =  MAX_RW_COUNT;
 
+	if (file->f_op->read)
+		ret = file->f_op->read(file, buf, count, pos);
+	else if (file->f_op->read_iter)
+		ret = new_sync_read(file, buf, count, pos);
+	else
+		ret = -EINVAL;
+	if (ret > 0) {
+		fsnotify_access(file);
+		add_rchar(current, ret);
+	}
+	inc_syscr(current);
 	return ret;
 }
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 21613bf1b49690..522d04843d4175 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1917,7 +1917,6 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
 			      struct iovec *fast_pointer,
 			      struct iovec **ret_pointer);
 
-extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
 extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
 extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
 extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 13/13] fs: don't change the address limit for ->read_iter in __kernel_read
  2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
                   ` (11 preceding siblings ...)
  2020-06-15 12:12 ` [PATCH 12/13] fs: remove __vfs_read Christoph Hellwig
@ 2020-06-15 12:12 ` Christoph Hellwig
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 12:12 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

If we read to a file that implements ->read_iter there is no need
to change the address limit if we send a kvec down.  Implement that
case, and prefer it over using plain ->read with a changed address
limit if available.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/read_write.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 1d43da8554dc0d..3bde37aa63db6c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -421,7 +421,6 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
 
 ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
-	mm_segment_t old_fs = get_fs();
 	ssize_t ret;
 
 	if (!(file->f_mode & FMODE_CAN_READ))
@@ -429,14 +428,25 @@ ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 
 	if (count > MAX_RW_COUNT)
 		count =  MAX_RW_COUNT;
-	set_fs(KERNEL_DS);
-	if (file->f_op->read)
+	if (file->f_op->read_iter) {
+		struct kvec iov = { .iov_base = buf, .iov_len = count };
+		struct kiocb kiocb;
+		struct iov_iter iter;
+
+		init_sync_kiocb(&kiocb, file);
+		kiocb.ki_pos = *pos;
+		iov_iter_kvec(&iter, READ, &iov, 1, count);
+		ret = file->f_op->read_iter(&kiocb, &iter);
+		*pos = kiocb.ki_pos;
+	} else if (file->f_op->read) {
+		mm_segment_t old_fs = get_fs();
+
+		set_fs(KERNEL_DS);
 		ret = file->f_op->read(file, (void __user *)buf, count, pos);
-	else if (file->f_op->read_iter)
-		ret = new_sync_read(file, (void __user *)buf, count, pos);
-	else
+		set_fs(old_fs);
+	} else {
 		ret = -EINVAL;
-	set_fs(old_fs);
+	}
 	if (ret > 0) {
 		fsnotify_access(file);
 		add_rchar(current, ret);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 12:12 ` [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write Christoph Hellwig
@ 2020-06-15 12:34   ` Matthew Wilcox
  2020-06-15 13:48     ` Christoph Hellwig
  2020-06-15 16:39   ` Linus Torvalds
  1 sibling, 1 reply; 21+ messages in thread
From: Matthew Wilcox @ 2020-06-15 12:34 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Al Viro, Linus Torvalds, Ian Kent, David Howells, linux-kernel,
	linux-fsdevel, linux-security-module, netfilter-devel

On Mon, Jun 15, 2020 at 02:12:49PM +0200, Christoph Hellwig wrote:
> We still need to check if the fѕ is open write, even for the low-level
> helper.

Do we need the analogous check for FMODE_READ in the __kernel_read()
patch?

> @@ -505,6 +505,8 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
>  	const char __user *p;
>  	ssize_t ret;
>  
> +	if (!(file->f_mode & FMODE_WRITE))
> +		return -EBADF;
>  	if (!(file->f_mode & FMODE_CAN_WRITE))
>  		return -EINVAL;
>  
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 12:34   ` Matthew Wilcox
@ 2020-06-15 13:48     ` Christoph Hellwig
  0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 13:48 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Christoph Hellwig, Al Viro, Linus Torvalds, Ian Kent,
	David Howells, linux-kernel, linux-fsdevel,
	linux-security-module, netfilter-devel

On Mon, Jun 15, 2020 at 05:34:39AM -0700, Matthew Wilcox wrote:
> On Mon, Jun 15, 2020 at 02:12:49PM +0200, Christoph Hellwig wrote:
> > We still need to check if the fѕ is open write, even for the low-level
> > helper.
> 
> Do we need the analogous check for FMODE_READ in the __kernel_read()
> patch?

Yes, we should probably grow it.  Hoping that none of the caller
actually wants to mess with files not open for reading as some of them
are rather dodgy.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 12:12 ` [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write Christoph Hellwig
  2020-06-15 12:34   ` Matthew Wilcox
@ 2020-06-15 16:39   ` Linus Torvalds
  2020-06-15 16:42     ` Christoph Hellwig
  2020-06-17 14:59     ` David Laight
  1 sibling, 2 replies; 21+ messages in thread
From: Linus Torvalds @ 2020-06-15 16:39 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Al Viro, Ian Kent, David Howells, Linux Kernel Mailing List,
	linux-fsdevel, LSM List, NetFilter

On Mon, Jun 15, 2020 at 5:13 AM Christoph Hellwig <hch@lst.de> wrote:
>
> We still need to check if the fѕ is open write, even for the low-level
> helper.

Is there actually a way to trigger something like this? I'm wondering
if it's worth a WARN_ON_ONCE()?

It doesn't sound sensible to have some kernel functionality try to
write to a file it didn't open for write, and sounds like a kernel bug
if this case were to ever trigger..

                Linus

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 16:39   ` Linus Torvalds
@ 2020-06-15 16:42     ` Christoph Hellwig
  2020-06-17 14:59     ` David Laight
  1 sibling, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2020-06-15 16:42 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Christoph Hellwig, Al Viro, Ian Kent, David Howells,
	Linux Kernel Mailing List, linux-fsdevel, LSM List, NetFilter

On Mon, Jun 15, 2020 at 09:39:31AM -0700, Linus Torvalds wrote:
> On Mon, Jun 15, 2020 at 5:13 AM Christoph Hellwig <hch@lst.de> wrote:
> >
> > We still need to check if the fѕ is open write, even for the low-level
> > helper.
> 
> Is there actually a way to trigger something like this? I'm wondering
> if it's worth a WARN_ON_ONCE()?
> 
> It doesn't sound sensible to have some kernel functionality try to
> write to a file it didn't open for write, and sounds like a kernel bug
> if this case were to ever trigger..

Yes, this would be bug in the calling code.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 10/13] integrity/ima: switch to using __kernel_read
  2020-06-15 12:12 ` [PATCH 10/13] integrity/ima: switch to using __kernel_read Christoph Hellwig
@ 2020-06-15 16:46   ` Linus Torvalds
  2020-06-15 16:56     ` Linus Torvalds
  0 siblings, 1 reply; 21+ messages in thread
From: Linus Torvalds @ 2020-06-15 16:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Al Viro, Ian Kent, David Howells, Linux Kernel Mailing List,
	linux-fsdevel, LSM List, NetFilter

On Mon, Jun 15, 2020 at 5:13 AM Christoph Hellwig <hch@lst.de> wrote:
>
> __kernel_read has a bunch of additional sanity checks, and this moves
> the set_fs out of non-core code.

Wel, you also seem to be removing this part:

> -       if (!(file->f_mode & FMODE_READ))
> -               return -EBADF;

which you didn't add in the previous patch that implemented __kernel_read().

It worries me that you're making these kinds of transformations where
the comments imply it's a no-op, but the actual code doesn't agree.

Especially when it's part of one large patch series and each commit
looks trivial.

This kind of series needs more care. Maybe that test isn't necessary,
but it isn't obvious, and I really don't like how you completely
glossed over totally changing what the code did.

               Linus

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 10/13] integrity/ima: switch to using __kernel_read
  2020-06-15 16:46   ` Linus Torvalds
@ 2020-06-15 16:56     ` Linus Torvalds
  0 siblings, 0 replies; 21+ messages in thread
From: Linus Torvalds @ 2020-06-15 16:56 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Al Viro, Ian Kent, David Howells, Linux Kernel Mailing List,
	linux-fsdevel, LSM List, NetFilter

On Mon, Jun 15, 2020 at 9:46 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> It worries me that you're making these kinds of transformations where
> the comments imply it's a no-op, but the actual code doesn't agree.

Note that it's not that I think the FMODE_READ check is necessarily
_needed_. It's more the discrepancy between the commit message and the
code change that I don't like.

The commit message implies that __kernel_read() has _more_ checks than
the checks done by integrity_kernel_read(). But it looks like they
aren't so much "more" as they are just "different".

                Linus

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write
  2020-06-15 16:39   ` Linus Torvalds
  2020-06-15 16:42     ` Christoph Hellwig
@ 2020-06-17 14:59     ` David Laight
  1 sibling, 0 replies; 21+ messages in thread
From: David Laight @ 2020-06-17 14:59 UTC (permalink / raw)
  To: 'Linus Torvalds', Christoph Hellwig
  Cc: Al Viro, Ian Kent, David Howells, Linux Kernel Mailing List,
	linux-fsdevel, LSM List, NetFilter

From: Linus Torvalds
> Sent: 15 June 2020 17:40
> On Mon, Jun 15, 2020 at 5:13 AM Christoph Hellwig <hch@lst.de> wrote:
> >
> > We still need to check if the fѕ is open write, even for the low-level
> > helper.
> 
> Is there actually a way to trigger something like this? I'm wondering
> if it's worth a WARN_ON_ONCE()?
> 
> It doesn't sound sensible to have some kernel functionality try to
> write to a file it didn't open for write, and sounds like a kernel bug
> if this case were to ever trigger..

It's a cheap test at the top of some fairly heavy code.
Failing the request will soon identify the bug.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2020-06-17 14:59 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-15 12:12 clean up kernel_{read,write} & friends v4 Christoph Hellwig
2020-06-15 12:12 ` [PATCH 01/13] cachefiles: switch to kernel_write Christoph Hellwig
2020-06-15 12:12 ` [PATCH 02/13] autofs: " Christoph Hellwig
2020-06-15 12:12 ` [PATCH 03/13] bpfilter: " Christoph Hellwig
2020-06-15 12:12 ` [PATCH 04/13] fs: unexport __kernel_write Christoph Hellwig
2020-06-15 12:12 ` [PATCH 05/13] fs: check FMODE_WRITE in __kernel_write Christoph Hellwig
2020-06-15 12:34   ` Matthew Wilcox
2020-06-15 13:48     ` Christoph Hellwig
2020-06-15 16:39   ` Linus Torvalds
2020-06-15 16:42     ` Christoph Hellwig
2020-06-17 14:59     ` David Laight
2020-06-15 12:12 ` [PATCH 06/13] fs: implement kernel_write using __kernel_write Christoph Hellwig
2020-06-15 12:12 ` [PATCH 07/13] fs: remove __vfs_write Christoph Hellwig
2020-06-15 12:12 ` [PATCH 08/13] fs: don't change the address limit for ->write_iter in __kernel_write Christoph Hellwig
2020-06-15 12:12 ` [PATCH 09/13] fs: add a __kernel_read helper Christoph Hellwig
2020-06-15 12:12 ` [PATCH 10/13] integrity/ima: switch to using __kernel_read Christoph Hellwig
2020-06-15 16:46   ` Linus Torvalds
2020-06-15 16:56     ` Linus Torvalds
2020-06-15 12:12 ` [PATCH 11/13] fs: implement kernel_read " Christoph Hellwig
2020-06-15 12:12 ` [PATCH 12/13] fs: remove __vfs_read Christoph Hellwig
2020-06-15 12:12 ` [PATCH 13/13] fs: don't change the address limit for ->read_iter in __kernel_read Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).