Linux-Fsdevel Archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Prepare for fsnotify pre-content permission events
@ 2023-12-10 14:18 Amir Goldstein
  2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:18 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

Hi Christian,

This v2 of pre-content event prep patches addresses some comments and
replaces the v1 patches [1] that are currently applied to vfs.rw.

I started with a new cleanup patch for ssize_t return type that you
suggested.

Patch 2 has a fix for a build error reported by kernel tests robot
(moved MAX_RW_COUNT capping to splice_file_range()), so I did not
retain the RVBs for this patch.

Patches 3,4 are unchanged and retain their RVBs.

Patch 5 changes the fsnotify hook name, so RBVs not retained.

Thanks,
Amir.

Changes since v1 [1]:
- Move MAX_RW_COUNT capping to splice_file_range() to fix build error
- Cleanup splice helpers return type
- Change fsnotify hook name to fsnotify_file_area_perm()
- Add RVBs

[1] https://lore.kernel.org/r/20231207123825.4011620-1-amir73il@gmail.com/

Amir Goldstein (5):
  splice: return type ssize_t from all helpers
  fs: use splice_copy_file_range() inline helper
  fsnotify: split fsnotify_perm() into two hooks
  fsnotify: assert that file_start_write() is not held in permission
    hooks
  fsnotify: optionally pass access range in file permission hooks

 fs/ceph/file.c           |  4 +--
 fs/fuse/file.c           |  5 +--
 fs/nfs/nfs4file.c        |  5 +--
 fs/open.c                |  4 +++
 fs/overlayfs/copy_up.c   |  2 +-
 fs/read_write.c          | 46 ++++++---------------------
 fs/readdir.c             |  4 +++
 fs/remap_range.c         |  8 ++++-
 fs/smb/client/cifsfs.c   |  5 +--
 fs/splice.c              | 69 ++++++++++++++++++++--------------------
 include/linux/fs.h       |  3 --
 include/linux/fsnotify.h | 50 ++++++++++++++++++++---------
 include/linux/splice.h   | 50 ++++++++++++++++-------------
 io_uring/splice.c        |  4 +--
 security/security.c      | 10 ++----
 15 files changed, 138 insertions(+), 131 deletions(-)

-- 
2.34.1


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

* [PATCH v2 1/5] splice: return type ssize_t from all helpers
  2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
@ 2023-12-10 14:18 ` Amir Goldstein
  2023-12-11  6:57   ` Amir Goldstein
  2023-12-11 14:39   ` Jan Kara
  2023-12-10 14:18 ` [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper Amir Goldstein
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:18 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

Not sure why some splice helpers return long, maybe historic reasons.
Change them all to return ssize_t to conform to the splice methods and
to the rest of the helpers.

Suggested-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/r/20231208-horchen-helium-d3ec1535ede5@brauner/
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/overlayfs/copy_up.c |  2 +-
 fs/read_write.c        |  2 +-
 fs/splice.c            | 62 +++++++++++++++++++++---------------------
 include/linux/splice.h | 43 ++++++++++++++---------------
 io_uring/splice.c      |  4 +--
 5 files changed, 56 insertions(+), 57 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 294b330aba9f..741d38058337 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -285,7 +285,7 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
 
 	while (len) {
 		size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
-		long bytes;
+		ssize_t bytes;
 
 		if (len < this_len)
 			this_len = len;
diff --git a/fs/read_write.c b/fs/read_write.c
index 01a14570015b..7783b8522693 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1214,7 +1214,7 @@ COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
 #endif /* CONFIG_COMPAT */
 
 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
-		  	   size_t count, loff_t max)
+			   size_t count, loff_t max)
 {
 	struct fd in, out;
 	struct inode *in_inode, *out_inode;
diff --git a/fs/splice.c b/fs/splice.c
index 7cda013e5a1e..6c1f12872407 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -932,8 +932,8 @@ static int warn_unsupported(struct file *file, const char *op)
 /*
  * Attempt to initiate a splice from pipe to file.
  */
-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-			   loff_t *ppos, size_t len, unsigned int flags)
+static ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+			      loff_t *ppos, size_t len, unsigned int flags)
 {
 	if (unlikely(!out->f_op->splice_write))
 		return warn_unsupported(out, "write");
@@ -955,9 +955,9 @@ static void do_splice_eof(struct splice_desc *sd)
  * Callers already called rw_verify_area() on the entire range.
  * No need to call it for sub ranges.
  */
-static long do_splice_read(struct file *in, loff_t *ppos,
-			   struct pipe_inode_info *pipe, size_t len,
-			   unsigned int flags)
+static size_t do_splice_read(struct file *in, loff_t *ppos,
+			     struct pipe_inode_info *pipe, size_t len,
+			     unsigned int flags)
 {
 	unsigned int p_space;
 
@@ -999,11 +999,11 @@ static long do_splice_read(struct file *in, loff_t *ppos,
  * If successful, it returns the amount of data spliced, 0 if it hit the EOF or
  * a hole and a negative error code otherwise.
  */
-long vfs_splice_read(struct file *in, loff_t *ppos,
-		     struct pipe_inode_info *pipe, size_t len,
-		     unsigned int flags)
+ssize_t vfs_splice_read(struct file *in, loff_t *ppos,
+			struct pipe_inode_info *pipe, size_t len,
+			unsigned int flags)
 {
-	int ret;
+	ssize_t ret;
 
 	ret = rw_verify_area(READ, in, ppos, len);
 	if (unlikely(ret < 0))
@@ -1030,7 +1030,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
 			       splice_direct_actor *actor)
 {
 	struct pipe_inode_info *pipe;
-	long ret, bytes;
+	size_t ret, bytes;
 	size_t len;
 	int i, flags, more;
 
@@ -1181,7 +1181,7 @@ static void direct_file_splice_eof(struct splice_desc *sd)
 		file->f_op->splice_eof(file);
 }
 
-static long do_splice_direct_actor(struct file *in, loff_t *ppos,
+static ssize_t do_splice_direct_actor(struct file *in, loff_t *ppos,
 				   struct file *out, loff_t *opos,
 				   size_t len, unsigned int flags,
 				   splice_direct_actor *actor)
@@ -1226,8 +1226,8 @@ static long do_splice_direct_actor(struct file *in, loff_t *ppos,
  *
  * Callers already called rw_verify_area() on the entire range.
  */
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-		      loff_t *opos, size_t len, unsigned int flags)
+ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+			 loff_t *opos, size_t len, unsigned int flags)
 {
 	return do_splice_direct_actor(in, ppos, out, opos, len, flags,
 				      direct_splice_actor);
@@ -1249,8 +1249,8 @@ EXPORT_SYMBOL(do_splice_direct);
  *
  * Callers already called rw_verify_area() on the entire range.
  */
-long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
-		       loff_t *opos, size_t len)
+ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
+			  loff_t *opos, size_t len)
 {
 	lockdep_assert(file_write_started(out));
 
@@ -1280,12 +1280,12 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
 			       struct pipe_inode_info *opipe,
 			       size_t len, unsigned int flags);
 
-long splice_file_to_pipe(struct file *in,
-			 struct pipe_inode_info *opipe,
-			 loff_t *offset,
-			 size_t len, unsigned int flags)
+ssize_t splice_file_to_pipe(struct file *in,
+			    struct pipe_inode_info *opipe,
+			    loff_t *offset,
+			    size_t len, unsigned int flags)
 {
-	long ret;
+	ssize_t ret;
 
 	pipe_lock(opipe);
 	ret = wait_for_space(opipe, flags);
@@ -1300,13 +1300,13 @@ long splice_file_to_pipe(struct file *in,
 /*
  * Determine where to splice to/from.
  */
-long do_splice(struct file *in, loff_t *off_in, struct file *out,
-	       loff_t *off_out, size_t len, unsigned int flags)
+ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out,
+		  loff_t *off_out, size_t len, unsigned int flags)
 {
 	struct pipe_inode_info *ipipe;
 	struct pipe_inode_info *opipe;
 	loff_t offset;
-	long ret;
+	ssize_t ret;
 
 	if (unlikely(!(in->f_mode & FMODE_READ) ||
 		     !(out->f_mode & FMODE_WRITE)))
@@ -1397,14 +1397,14 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
 	return ret;
 }
 
-static long __do_splice(struct file *in, loff_t __user *off_in,
-			struct file *out, loff_t __user *off_out,
-			size_t len, unsigned int flags)
+static ssize_t __do_splice(struct file *in, loff_t __user *off_in,
+			   struct file *out, loff_t __user *off_out,
+			   size_t len, unsigned int flags)
 {
 	struct pipe_inode_info *ipipe;
 	struct pipe_inode_info *opipe;
 	loff_t offset, *__off_in = NULL, *__off_out = NULL;
-	long ret;
+	ssize_t ret;
 
 	ipipe = get_pipe_info(in, true);
 	opipe = get_pipe_info(out, true);
@@ -1634,7 +1634,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
 		size_t, len, unsigned int, flags)
 {
 	struct fd in, out;
-	long error;
+	ssize_t error;
 
 	if (unlikely(!len))
 		return 0;
@@ -1648,7 +1648,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
 		out = fdget(fd_out);
 		if (out.file) {
 			error = __do_splice(in.file, off_in, out.file, off_out,
-						len, flags);
+					    len, flags);
 			fdput(out);
 		}
 		fdput(in);
@@ -1962,7 +1962,7 @@ static int link_pipe(struct pipe_inode_info *ipipe,
  * The 'flags' used are the SPLICE_F_* variants, currently the only
  * applicable one is SPLICE_F_NONBLOCK.
  */
-long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
+ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
 {
 	struct pipe_inode_info *ipipe = get_pipe_info(in, true);
 	struct pipe_inode_info *opipe = get_pipe_info(out, true);
@@ -2003,7 +2003,7 @@ long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
 SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
 {
 	struct fd in, out;
-	int error;
+	ssize_t error;
 
 	if (unlikely(flags & ~SPLICE_F_ALL))
 		return -EINVAL;
diff --git a/include/linux/splice.h b/include/linux/splice.h
index 49532d5dda52..068a8e8ffd73 100644
--- a/include/linux/splice.h
+++ b/include/linux/splice.h
@@ -68,31 +68,30 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
 typedef int (splice_direct_actor)(struct pipe_inode_info *,
 				  struct splice_desc *);
 
-extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
-				loff_t *, size_t, unsigned int,
-				splice_actor *);
-extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
-				  struct splice_desc *, splice_actor *);
-extern ssize_t splice_to_pipe(struct pipe_inode_info *,
-			      struct splice_pipe_desc *);
-extern ssize_t add_to_pipe(struct pipe_inode_info *,
-			      struct pipe_buffer *);
-long vfs_splice_read(struct file *in, loff_t *ppos,
-		     struct pipe_inode_info *pipe, size_t len,
-		     unsigned int flags);
+ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
+			 loff_t *ppos, size_t len, unsigned int flags,
+			 splice_actor *actor);
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
+			   struct splice_desc *sd, splice_actor *actor);
+ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+			      struct splice_pipe_desc *spd);
+ssize_t add_to_pipe(struct pipe_inode_info *pipe, struct pipe_buffer *buf);
+ssize_t vfs_splice_read(struct file *in, loff_t *ppos,
+			struct pipe_inode_info *pipe, size_t len,
+			unsigned int flags);
 ssize_t splice_direct_to_actor(struct file *file, struct splice_desc *sd,
 			       splice_direct_actor *actor);
-long do_splice(struct file *in, loff_t *off_in, struct file *out,
-	       loff_t *off_out, size_t len, unsigned int flags);
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-		      loff_t *opos, size_t len, unsigned int flags);
-long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
-		       loff_t *opos, size_t len);
+ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out,
+		  loff_t *off_out, size_t len, unsigned int flags);
+ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+			 loff_t *opos, size_t len, unsigned int flags);
+ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
+			  loff_t *opos, size_t len);
 
-extern long do_tee(struct file *in, struct file *out, size_t len,
-		   unsigned int flags);
-extern ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
-				loff_t *ppos, size_t len, unsigned int flags);
+ssize_t do_tee(struct file *in, struct file *out, size_t len,
+	       unsigned int flags);
+ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
+			 loff_t *ppos, size_t len, unsigned int flags);
 
 /*
  * for dynamic pipe sizing
diff --git a/io_uring/splice.c b/io_uring/splice.c
index 7c4469e9540e..3b659cd23e9d 100644
--- a/io_uring/splice.c
+++ b/io_uring/splice.c
@@ -51,7 +51,7 @@ int io_tee(struct io_kiocb *req, unsigned int issue_flags)
 	struct file *out = sp->file_out;
 	unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
 	struct file *in;
-	long ret = 0;
+	ssize_t ret = 0;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
@@ -92,7 +92,7 @@ int io_splice(struct io_kiocb *req, unsigned int issue_flags)
 	unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
 	loff_t *poff_in, *poff_out;
 	struct file *in;
-	long ret = 0;
+	ssize_t ret = 0;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-- 
2.34.1


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

* [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper
  2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
  2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
@ 2023-12-10 14:18 ` Amir Goldstein
  2023-12-11 14:45   ` Jan Kara
  2023-12-10 14:18 ` [PATCH v2 3/5] fsnotify: split fsnotify_perm() into two hooks Amir Goldstein
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:18 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

generic_copy_file_range() is just a wrapper around splice_file_range(),
which caps the maximum copy length.

The only caller of splice_file_range(), namely __ceph_copy_file_range()
is already ready to cope with short copy.

Move the length capping into splice_file_range() and replace the exported
symbol generic_copy_file_range() with a simple inline helper.

Suggested-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/linux-fsdevel/20231204083849.GC32438@lst.de/
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/ceph/file.c         |  4 ++--
 fs/fuse/file.c         |  5 +++--
 fs/nfs/nfs4file.c      |  5 +++--
 fs/read_write.c        | 34 ----------------------------------
 fs/smb/client/cifsfs.c |  5 +++--
 fs/splice.c            |  7 ++++---
 include/linux/fs.h     |  3 ---
 include/linux/splice.h |  7 +++++++
 8 files changed, 22 insertions(+), 48 deletions(-)

diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index f11de6e1f1c1..d380d9dad0e0 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -3090,8 +3090,8 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off,
 				     len, flags);
 
 	if (ret == -EOPNOTSUPP || ret == -EXDEV)
-		ret = generic_copy_file_range(src_file, src_off, dst_file,
-					      dst_off, len, flags);
+		ret = splice_copy_file_range(src_file, src_off, dst_file,
+					     dst_off, len);
 	return ret;
 }
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a660f1f21540..148a71b8b4d0 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -19,6 +19,7 @@
 #include <linux/uio.h>
 #include <linux/fs.h>
 #include <linux/filelock.h>
+#include <linux/splice.h>
 
 static int fuse_send_open(struct fuse_mount *fm, u64 nodeid,
 			  unsigned int open_flags, int opcode,
@@ -3195,8 +3196,8 @@ static ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off,
 				     len, flags);
 
 	if (ret == -EOPNOTSUPP || ret == -EXDEV)
-		ret = generic_copy_file_range(src_file, src_off, dst_file,
-					      dst_off, len, flags);
+		ret = splice_copy_file_range(src_file, src_off, dst_file,
+					     dst_off, len);
 	return ret;
 }
 
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 02788c3c85e5..e238abc78a13 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -10,6 +10,7 @@
 #include <linux/mount.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_ssc.h>
+#include <linux/splice.h>
 #include "delegation.h"
 #include "internal.h"
 #include "iostat.h"
@@ -195,8 +196,8 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
 	ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count,
 				     flags);
 	if (ret == -EOPNOTSUPP || ret == -EXDEV)
-		ret = generic_copy_file_range(file_in, pos_in, file_out,
-					      pos_out, count, flags);
+		ret = splice_copy_file_range(file_in, pos_in, file_out,
+					     pos_out, count);
 	return ret;
 }
 
diff --git a/fs/read_write.c b/fs/read_write.c
index 7783b8522693..e3abf603eaaf 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1396,40 +1396,6 @@ COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
 }
 #endif
 
-/**
- * generic_copy_file_range - copy data between two files
- * @file_in:	file structure to read from
- * @pos_in:	file offset to read from
- * @file_out:	file structure to write data to
- * @pos_out:	file offset to write data to
- * @len:	amount of data to copy
- * @flags:	copy flags
- *
- * This is a generic filesystem helper to copy data from one file to another.
- * It has no constraints on the source or destination file owners - the files
- * can belong to different superblocks and different filesystem types. Short
- * copies are allowed.
- *
- * This should be called from the @file_out filesystem, as per the
- * ->copy_file_range() method.
- *
- * Returns the number of bytes copied or a negative error indicating the
- * failure.
- */
-
-ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
-				struct file *file_out, loff_t pos_out,
-				size_t len, unsigned int flags)
-{
-	/* May only be called from within ->copy_file_range() methods */
-	if (WARN_ON_ONCE(flags))
-		return -EINVAL;
-
-	return splice_file_range(file_in, &pos_in, file_out, &pos_out,
-				 min_t(size_t, len, MAX_RW_COUNT));
-}
-EXPORT_SYMBOL(generic_copy_file_range);
-
 /*
  * Performs necessary checks before doing a file copy
  *
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index ea3a7a668b45..ee461bf0ef63 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -25,6 +25,7 @@
 #include <linux/freezer.h>
 #include <linux/namei.h>
 #include <linux/random.h>
+#include <linux/splice.h>
 #include <linux/uuid.h>
 #include <linux/xattr.h>
 #include <uapi/linux/magic.h>
@@ -1362,8 +1363,8 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
 	free_xid(xid);
 
 	if (rc == -EOPNOTSUPP || rc == -EXDEV)
-		rc = generic_copy_file_range(src_file, off, dst_file,
-					     destoff, len, flags);
+		rc = splice_copy_file_range(src_file, off, dst_file,
+					    destoff, len);
 	return rc;
 }
 
diff --git a/fs/splice.c b/fs/splice.c
index 6c1f12872407..5f534bedc25a 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1243,7 +1243,7 @@ EXPORT_SYMBOL(do_splice_direct);
  * @len:	number of bytes to splice
  *
  * Description:
- *    For use by generic_copy_file_range() and ->copy_file_range() methods.
+ *    For use by ->copy_file_range() methods.
  *    Like do_splice_direct(), but vfs_copy_file_range() already holds
  *    start_file_write() on @out file.
  *
@@ -1254,8 +1254,9 @@ ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
 {
 	lockdep_assert(file_write_started(out));
 
-	return do_splice_direct_actor(in, ppos, out, opos, len, 0,
-				      splice_file_range_actor);
+	return do_splice_direct_actor(in, ppos, out, opos,
+				      min_t(size_t, len, MAX_RW_COUNT),
+				      0, splice_file_range_actor);
 }
 EXPORT_SYMBOL(splice_file_range);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 04422a0eccdd..900d0cd55b50 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2090,9 +2090,6 @@ 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_copy_file_range(struct file *, loff_t , struct file *,
 				   loff_t, size_t, unsigned int);
-extern ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
-				       struct file *file_out, loff_t pos_out,
-				       size_t len, unsigned int flags);
 int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 				    struct file *file_out, loff_t pos_out,
 				    loff_t *len, unsigned int remap_flags,
diff --git a/include/linux/splice.h b/include/linux/splice.h
index 068a8e8ffd73..9dec4861d09f 100644
--- a/include/linux/splice.h
+++ b/include/linux/splice.h
@@ -88,6 +88,13 @@ ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
 			  loff_t *opos, size_t len);
 
+static inline long splice_copy_file_range(struct file *in, loff_t pos_in,
+					  struct file *out, loff_t pos_out,
+					  size_t len)
+{
+	return splice_file_range(in, &pos_in, out, &pos_out, len);
+}
+
 ssize_t do_tee(struct file *in, struct file *out, size_t len,
 	       unsigned int flags);
 ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
-- 
2.34.1


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

* [PATCH v2 3/5] fsnotify: split fsnotify_perm() into two hooks
  2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
  2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
  2023-12-10 14:18 ` [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper Amir Goldstein
@ 2023-12-10 14:18 ` Amir Goldstein
  2023-12-10 14:19 ` [PATCH v2 4/5] fsnotify: assert that file_start_write() is not held in permission hooks Amir Goldstein
  2023-12-10 14:19 ` [PATCH v2 5/5] fsnotify: optionally pass access range in file " Amir Goldstein
  4 siblings, 0 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:18 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

We would like to make changes to the fsnotify access permission hook -
add file range arguments and add the pre modify event.

In preparation for these changes, split the fsnotify_perm() hook into
fsnotify_open_perm() and fsnotify_file_perm().

This is needed for fanotify "pre content" events.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 include/linux/fsnotify.h | 34 +++++++++++++++++++---------------
 security/security.c      |  4 ++--
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index bcb6609b54b3..926bb4461b9e 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -100,29 +100,33 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
 	return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
 }
 
-/* Simple call site for access decisions */
-static inline int fsnotify_perm(struct file *file, int mask)
+/*
+ * fsnotify_file_perm - permission hook before file access
+ */
+static inline int fsnotify_file_perm(struct file *file, int perm_mask)
 {
-	int ret;
-	__u32 fsnotify_mask = 0;
+	__u32 fsnotify_mask = FS_ACCESS_PERM;
 
-	if (!(mask & (MAY_READ | MAY_OPEN)))
+	if (!(perm_mask & MAY_READ))
 		return 0;
 
-	if (mask & MAY_OPEN) {
-		fsnotify_mask = FS_OPEN_PERM;
+	return fsnotify_file(file, fsnotify_mask);
+}
 
-		if (file->f_flags & __FMODE_EXEC) {
-			ret = fsnotify_file(file, FS_OPEN_EXEC_PERM);
+/*
+ * fsnotify_open_perm - permission hook before file open
+ */
+static inline int fsnotify_open_perm(struct file *file)
+{
+	int ret;
 
-			if (ret)
-				return ret;
-		}
-	} else if (mask & MAY_READ) {
-		fsnotify_mask = FS_ACCESS_PERM;
+	if (file->f_flags & __FMODE_EXEC) {
+		ret = fsnotify_file(file, FS_OPEN_EXEC_PERM);
+		if (ret)
+			return ret;
 	}
 
-	return fsnotify_file(file, fsnotify_mask);
+	return fsnotify_file(file, FS_OPEN_PERM);
 }
 
 /*
diff --git a/security/security.c b/security/security.c
index dcb3e7014f9b..d7f3703c5905 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2586,7 +2586,7 @@ int security_file_permission(struct file *file, int mask)
 	if (ret)
 		return ret;
 
-	return fsnotify_perm(file, mask);
+	return fsnotify_file_perm(file, mask);
 }
 
 /**
@@ -2837,7 +2837,7 @@ int security_file_open(struct file *file)
 	if (ret)
 		return ret;
 
-	return fsnotify_perm(file, MAY_OPEN);
+	return fsnotify_open_perm(file);
 }
 
 /**
-- 
2.34.1


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

* [PATCH v2 4/5] fsnotify: assert that file_start_write() is not held in permission hooks
  2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
                   ` (2 preceding siblings ...)
  2023-12-10 14:18 ` [PATCH v2 3/5] fsnotify: split fsnotify_perm() into two hooks Amir Goldstein
@ 2023-12-10 14:19 ` Amir Goldstein
  2023-12-10 14:19 ` [PATCH v2 5/5] fsnotify: optionally pass access range in file " Amir Goldstein
  4 siblings, 0 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:19 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

filesystem may be modified in the context of fanotify permission events
(e.g. by HSM service), so assert that sb freeze protection is not held.

If the assertion fails, then the following deadlock would be possible:

CPU0				CPU1			CPU2
-------------------------------------------------------------------------
file_start_write()#0
...
  fsnotify_perm()
    fanotify_get_response() =>	(read event and fill file)
				...
				...			freeze_super()
				...			  sb_wait_write()
				...
				vfs_write()
				  file_start_write()#1

This example demonstrates a use case of an hierarchical storage management
(HSM) service that uses fanotify permission events to fill the content of
a file before access, while a 3rd process starts fsfreeze.

This creates a circular dependeny:
  file_start_write()#0 => fanotify_get_response =>
    file_start_write()#1 =>
      sb_wait_write() =>
        file_end_write()#0

Where file_end_write()#0 can never be called and none of the threads can
make progress.

The assertion is checked for both MAY_READ and MAY_WRITE permission
hooks in preparation for a pre-modify permission event.

The assertion is not checked for an open permission event, because
do_open() takes mnt_want_write() in O_TRUNC case, meaning that it is not
safe to write to filesystem in the content of an open permission event.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 include/linux/fsnotify.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 926bb4461b9e..0a9d6a8a747a 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -107,6 +107,13 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
 {
 	__u32 fsnotify_mask = FS_ACCESS_PERM;
 
+	/*
+	 * filesystem may be modified in the context of permission events
+	 * (e.g. by HSM filling a file on access), so sb freeze protection
+	 * must not be held.
+	 */
+	lockdep_assert_once(file_write_not_started(file));
+
 	if (!(perm_mask & MAY_READ))
 		return 0;
 
-- 
2.34.1


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

* [PATCH v2 5/5] fsnotify: optionally pass access range in file permission hooks
  2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
                   ` (3 preceding siblings ...)
  2023-12-10 14:19 ` [PATCH v2 4/5] fsnotify: assert that file_start_write() is not held in permission hooks Amir Goldstein
@ 2023-12-10 14:19 ` Amir Goldstein
  2023-12-11 15:20   ` Jan Kara
  4 siblings, 1 reply; 11+ messages in thread
From: Amir Goldstein @ 2023-12-10 14:19 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

In preparation for pre-content permission events with file access range,
move fsnotify_file_perm() hook out of security_file_permission() and into
the callers.

Callers that have the access range information call the new hook
fsnotify_file_area_perm() with the access range.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/open.c                |  4 ++++
 fs/read_write.c          | 10 ++++++++--
 fs/readdir.c             |  4 ++++
 fs/remap_range.c         |  8 +++++++-
 include/linux/fsnotify.h | 13 +++++++++++--
 security/security.c      |  8 +-------
 6 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index 02dc608d40d8..d877228d5939 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -304,6 +304,10 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (ret)
 		return ret;
 
+	ret = fsnotify_file_area_perm(file, MAY_WRITE, &offset, len);
+	if (ret)
+		return ret;
+
 	if (S_ISFIFO(inode->i_mode))
 		return -ESPIPE;
 
diff --git a/fs/read_write.c b/fs/read_write.c
index e3abf603eaaf..d4c036e82b6c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -354,6 +354,9 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
 
 int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
 {
+	int mask = read_write == READ ? MAY_READ : MAY_WRITE;
+	int ret;
+
 	if (unlikely((ssize_t) count < 0))
 		return -EINVAL;
 
@@ -371,8 +374,11 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
 		}
 	}
 
-	return security_file_permission(file,
-				read_write == READ ? MAY_READ : MAY_WRITE);
+	ret = security_file_permission(file, mask);
+	if (ret)
+		return ret;
+
+	return fsnotify_file_area_perm(file, mask, ppos, count);
 }
 EXPORT_SYMBOL(rw_verify_area);
 
diff --git a/fs/readdir.c b/fs/readdir.c
index c8c46e294431..278bc0254732 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -96,6 +96,10 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
 	if (res)
 		goto out;
 
+	res = fsnotify_file_perm(file, MAY_READ);
+	if (res)
+		goto out;
+
 	res = down_read_killable(&inode->i_rwsem);
 	if (res)
 		goto out;
diff --git a/fs/remap_range.c b/fs/remap_range.c
index 12131f2a6c9e..f8c1120b8311 100644
--- a/fs/remap_range.c
+++ b/fs/remap_range.c
@@ -102,7 +102,9 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in,
 static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
 			     bool write)
 {
+	int mask = write ? MAY_WRITE : MAY_READ;
 	loff_t tmp;
+	int ret;
 
 	if (unlikely(pos < 0 || len < 0))
 		return -EINVAL;
@@ -110,7 +112,11 @@ static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
 	if (unlikely(check_add_overflow(pos, len, &tmp)))
 		return -EINVAL;
 
-	return security_file_permission(file, write ? MAY_WRITE : MAY_READ);
+	ret = security_file_permission(file, mask);
+	if (ret)
+		return ret;
+
+	return fsnotify_file_area_perm(file, mask, &pos, len);
 }
 
 /*
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 0a9d6a8a747a..11e6434b8e71 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -101,9 +101,10 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
 }
 
 /*
- * fsnotify_file_perm - permission hook before file access
+ * fsnotify_file_area_perm - permission hook before access to file range
  */
-static inline int fsnotify_file_perm(struct file *file, int perm_mask)
+static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
+					  const loff_t *ppos, size_t count)
 {
 	__u32 fsnotify_mask = FS_ACCESS_PERM;
 
@@ -120,6 +121,14 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
 	return fsnotify_file(file, fsnotify_mask);
 }
 
+/*
+ * fsnotify_file_perm - permission hook before file access
+ */
+static inline int fsnotify_file_perm(struct file *file, int perm_mask)
+{
+	return fsnotify_file_area_perm(file, perm_mask, NULL, 0);
+}
+
 /*
  * fsnotify_open_perm - permission hook before file open
  */
diff --git a/security/security.c b/security/security.c
index d7f3703c5905..2a7fc7881cbc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2580,13 +2580,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir,
  */
 int security_file_permission(struct file *file, int mask)
 {
-	int ret;
-
-	ret = call_int_hook(file_permission, 0, file, mask);
-	if (ret)
-		return ret;
-
-	return fsnotify_file_perm(file, mask);
+	return call_int_hook(file_permission, 0, file, mask);
 }
 
 /**
-- 
2.34.1


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

* Re: [PATCH v2 1/5] splice: return type ssize_t from all helpers
  2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
@ 2023-12-11  6:57   ` Amir Goldstein
  2023-12-11 14:39   ` Jan Kara
  1 sibling, 0 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-11  6:57 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jan Kara, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

On Sun, Dec 10, 2023 at 4:19 PM Amir Goldstein <amir73il@gmail.com> wrote:
>
> Not sure why some splice helpers return long, maybe historic reasons.
> Change them all to return ssize_t to conform to the splice methods and
> to the rest of the helpers.
>
> Suggested-by: Christian Brauner <brauner@kernel.org>
> Link: https://lore.kernel.org/r/20231208-horchen-helium-d3ec1535ede5@brauner/
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
>  fs/overlayfs/copy_up.c |  2 +-
>  fs/read_write.c        |  2 +-
>  fs/splice.c            | 62 +++++++++++++++++++++---------------------
>  include/linux/splice.h | 43 ++++++++++++++---------------
>  io_uring/splice.c      |  4 +--
>  5 files changed, 56 insertions(+), 57 deletions(-)
>
> diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
> index 294b330aba9f..741d38058337 100644
> --- a/fs/overlayfs/copy_up.c
> +++ b/fs/overlayfs/copy_up.c
> @@ -285,7 +285,7 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
>
>         while (len) {
>                 size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
> -               long bytes;
> +               ssize_t bytes;
>
>                 if (len < this_len)
>                         this_len = len;
> diff --git a/fs/read_write.c b/fs/read_write.c
> index 01a14570015b..7783b8522693 100644
> --- a/fs/read_write.c
> +++ b/fs/read_write.c
> @@ -1214,7 +1214,7 @@ COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
>  #endif /* CONFIG_COMPAT */
>
>  static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
> -                          size_t count, loff_t max)
> +                          size_t count, loff_t max)
>  {
>         struct fd in, out;
>         struct inode *in_inode, *out_inode;
> diff --git a/fs/splice.c b/fs/splice.c
> index 7cda013e5a1e..6c1f12872407 100644
> --- a/fs/splice.c
> +++ b/fs/splice.c
> @@ -932,8 +932,8 @@ static int warn_unsupported(struct file *file, const char *op)
>  /*
>   * Attempt to initiate a splice from pipe to file.
>   */
> -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
> -                          loff_t *ppos, size_t len, unsigned int flags)
> +static ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out,
> +                             loff_t *ppos, size_t len, unsigned int flags)
>  {
>         if (unlikely(!out->f_op->splice_write))
>                 return warn_unsupported(out, "write");
> @@ -955,9 +955,9 @@ static void do_splice_eof(struct splice_desc *sd)
>   * Callers already called rw_verify_area() on the entire range.
>   * No need to call it for sub ranges.
>   */
> -static long do_splice_read(struct file *in, loff_t *ppos,
> -                          struct pipe_inode_info *pipe, size_t len,
> -                          unsigned int flags)
> +static size_t do_splice_read(struct file *in, loff_t *ppos,
> +                            struct pipe_inode_info *pipe, size_t len,
> +                            unsigned int flags)
>  {
>         unsigned int p_space;
>
> @@ -999,11 +999,11 @@ static long do_splice_read(struct file *in, loff_t *ppos,
>   * If successful, it returns the amount of data spliced, 0 if it hit the EOF or
>   * a hole and a negative error code otherwise.
>   */
> -long vfs_splice_read(struct file *in, loff_t *ppos,
> -                    struct pipe_inode_info *pipe, size_t len,
> -                    unsigned int flags)
> +ssize_t vfs_splice_read(struct file *in, loff_t *ppos,
> +                       struct pipe_inode_info *pipe, size_t len,
> +                       unsigned int flags)
>  {
> -       int ret;
> +       ssize_t ret;
>
>         ret = rw_verify_area(READ, in, ppos, len);
>         if (unlikely(ret < 0))
> @@ -1030,7 +1030,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
>                                splice_direct_actor *actor)
>  {
>         struct pipe_inode_info *pipe;
> -       long ret, bytes;
> +       size_t ret, bytes;
>         size_t len;
>         int i, flags, more;
>
> @@ -1181,7 +1181,7 @@ static void direct_file_splice_eof(struct splice_desc *sd)
>                 file->f_op->splice_eof(file);
>  }
>
> -static long do_splice_direct_actor(struct file *in, loff_t *ppos,
> +static ssize_t do_splice_direct_actor(struct file *in, loff_t *ppos,
>                                    struct file *out, loff_t *opos,
>                                    size_t len, unsigned int flags,
>                                    splice_direct_actor *actor)
> @@ -1226,8 +1226,8 @@ static long do_splice_direct_actor(struct file *in, loff_t *ppos,
>   *
>   * Callers already called rw_verify_area() on the entire range.
>   */
> -long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
> -                     loff_t *opos, size_t len, unsigned int flags)
> +ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
> +                        loff_t *opos, size_t len, unsigned int flags)
>  {
>         return do_splice_direct_actor(in, ppos, out, opos, len, flags,
>                                       direct_splice_actor);
> @@ -1249,8 +1249,8 @@ EXPORT_SYMBOL(do_splice_direct);
>   *
>   * Callers already called rw_verify_area() on the entire range.
>   */
> -long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
> -                      loff_t *opos, size_t len)
> +ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
> +                         loff_t *opos, size_t len)
>  {
>         lockdep_assert(file_write_started(out));
>
> @@ -1280,12 +1280,12 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
>                                struct pipe_inode_info *opipe,
>                                size_t len, unsigned int flags);
>
> -long splice_file_to_pipe(struct file *in,
> -                        struct pipe_inode_info *opipe,
> -                        loff_t *offset,
> -                        size_t len, unsigned int flags)
> +ssize_t splice_file_to_pipe(struct file *in,
> +                           struct pipe_inode_info *opipe,
> +                           loff_t *offset,
> +                           size_t len, unsigned int flags)

OOPS forgot to fix the declaration in fs/internal.h

>  {
> -       long ret;
> +       ssize_t ret;
>
>         pipe_lock(opipe);
>         ret = wait_for_space(opipe, flags);
> @@ -1300,13 +1300,13 @@ long splice_file_to_pipe(struct file *in,
>  /*
>   * Determine where to splice to/from.
>   */
> -long do_splice(struct file *in, loff_t *off_in, struct file *out,
> -              loff_t *off_out, size_t len, unsigned int flags)
> +ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out,
> +                 loff_t *off_out, size_t len, unsigned int flags)
>  {
>         struct pipe_inode_info *ipipe;
>         struct pipe_inode_info *opipe;
>         loff_t offset;
> -       long ret;
> +       ssize_t ret;
>
>         if (unlikely(!(in->f_mode & FMODE_READ) ||
>                      !(out->f_mode & FMODE_WRITE)))
> @@ -1397,14 +1397,14 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
>         return ret;
>  }
>
> -static long __do_splice(struct file *in, loff_t __user *off_in,
> -                       struct file *out, loff_t __user *off_out,
> -                       size_t len, unsigned int flags)
> +static ssize_t __do_splice(struct file *in, loff_t __user *off_in,
> +                          struct file *out, loff_t __user *off_out,
> +                          size_t len, unsigned int flags)
>  {
>         struct pipe_inode_info *ipipe;
>         struct pipe_inode_info *opipe;
>         loff_t offset, *__off_in = NULL, *__off_out = NULL;
> -       long ret;
> +       ssize_t ret;
>
>         ipipe = get_pipe_info(in, true);
>         opipe = get_pipe_info(out, true);
> @@ -1634,7 +1634,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
>                 size_t, len, unsigned int, flags)
>  {
>         struct fd in, out;
> -       long error;
> +       ssize_t error;
>
>         if (unlikely(!len))
>                 return 0;
> @@ -1648,7 +1648,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
>                 out = fdget(fd_out);
>                 if (out.file) {
>                         error = __do_splice(in.file, off_in, out.file, off_out,
> -                                               len, flags);
> +                                           len, flags);
>                         fdput(out);
>                 }
>                 fdput(in);
> @@ -1962,7 +1962,7 @@ static int link_pipe(struct pipe_inode_info *ipipe,
>   * The 'flags' used are the SPLICE_F_* variants, currently the only
>   * applicable one is SPLICE_F_NONBLOCK.
>   */
> -long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
> +ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
>  {
>         struct pipe_inode_info *ipipe = get_pipe_info(in, true);
>         struct pipe_inode_info *opipe = get_pipe_info(out, true);
> @@ -2003,7 +2003,7 @@ long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
>  SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
>  {
>         struct fd in, out;
> -       int error;
> +       ssize_t error;
>
>         if (unlikely(flags & ~SPLICE_F_ALL))
>                 return -EINVAL;
> diff --git a/include/linux/splice.h b/include/linux/splice.h
> index 49532d5dda52..068a8e8ffd73 100644
> --- a/include/linux/splice.h
> +++ b/include/linux/splice.h
> @@ -68,31 +68,30 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
>  typedef int (splice_direct_actor)(struct pipe_inode_info *,
>                                   struct splice_desc *);
>
> -extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
> -                               loff_t *, size_t, unsigned int,
> -                               splice_actor *);
> -extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
> -                                 struct splice_desc *, splice_actor *);
> -extern ssize_t splice_to_pipe(struct pipe_inode_info *,
> -                             struct splice_pipe_desc *);
> -extern ssize_t add_to_pipe(struct pipe_inode_info *,
> -                             struct pipe_buffer *);
> -long vfs_splice_read(struct file *in, loff_t *ppos,
> -                    struct pipe_inode_info *pipe, size_t len,
> -                    unsigned int flags);
> +ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
> +                        loff_t *ppos, size_t len, unsigned int flags,
> +                        splice_actor *actor);
> +ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
> +                          struct splice_desc *sd, splice_actor *actor);
> +ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
> +                             struct splice_pipe_desc *spd);
> +ssize_t add_to_pipe(struct pipe_inode_info *pipe, struct pipe_buffer *buf);
> +ssize_t vfs_splice_read(struct file *in, loff_t *ppos,
> +                       struct pipe_inode_info *pipe, size_t len,
> +                       unsigned int flags);
>  ssize_t splice_direct_to_actor(struct file *file, struct splice_desc *sd,
>                                splice_direct_actor *actor);
> -long do_splice(struct file *in, loff_t *off_in, struct file *out,
> -              loff_t *off_out, size_t len, unsigned int flags);
> -long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
> -                     loff_t *opos, size_t len, unsigned int flags);
> -long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
> -                      loff_t *opos, size_t len);
> +ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out,
> +                 loff_t *off_out, size_t len, unsigned int flags);
> +ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
> +                        loff_t *opos, size_t len, unsigned int flags);
> +ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out,
> +                         loff_t *opos, size_t len);
>
> -extern long do_tee(struct file *in, struct file *out, size_t len,
> -                  unsigned int flags);
> -extern ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
> -                               loff_t *ppos, size_t len, unsigned int flags);
> +ssize_t do_tee(struct file *in, struct file *out, size_t len,
> +              unsigned int flags);
> +ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
> +                        loff_t *ppos, size_t len, unsigned int flags);
>
>  /*
>   * for dynamic pipe sizing
> diff --git a/io_uring/splice.c b/io_uring/splice.c
> index 7c4469e9540e..3b659cd23e9d 100644
> --- a/io_uring/splice.c
> +++ b/io_uring/splice.c
> @@ -51,7 +51,7 @@ int io_tee(struct io_kiocb *req, unsigned int issue_flags)
>         struct file *out = sp->file_out;
>         unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
>         struct file *in;
> -       long ret = 0;
> +       ssize_t ret = 0;
>
>         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
>
> @@ -92,7 +92,7 @@ int io_splice(struct io_kiocb *req, unsigned int issue_flags)
>         unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
>         loff_t *poff_in, *poff_out;
>         struct file *in;
> -       long ret = 0;
> +       ssize_t ret = 0;
>
>         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
>
> --
> 2.34.1
>

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

* Re: [PATCH v2 1/5] splice: return type ssize_t from all helpers
  2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
  2023-12-11  6:57   ` Amir Goldstein
@ 2023-12-11 14:39   ` Jan Kara
  2023-12-11 15:17     ` Amir Goldstein
  1 sibling, 1 reply; 11+ messages in thread
From: Jan Kara @ 2023-12-11 14:39 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Christian Brauner, Jan Kara, Jeff Layton, Josef Bacik,
	Christoph Hellwig, David Howells, Jens Axboe, Miklos Szeredi,
	Al Viro, linux-fsdevel

On Sun 10-12-23 16:18:57, Amir Goldstein wrote:
> Not sure why some splice helpers return long, maybe historic reasons.
> Change them all to return ssize_t to conform to the splice methods and
> to the rest of the helpers.
> 
> Suggested-by: Christian Brauner <brauner@kernel.org>
> Link: https://lore.kernel.org/r/20231208-horchen-helium-d3ec1535ede5@brauner/
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

> @@ -955,9 +955,9 @@ static void do_splice_eof(struct splice_desc *sd)
>   * Callers already called rw_verify_area() on the entire range.
>   * No need to call it for sub ranges.
>   */
> -static long do_splice_read(struct file *in, loff_t *ppos,
> -			   struct pipe_inode_info *pipe, size_t len,
> -			   unsigned int flags)
> +static size_t do_splice_read(struct file *in, loff_t *ppos,
          ^^^ ssize_t here?

> +			     struct pipe_inode_info *pipe, size_t len,
> +			     unsigned int flags)
>  {
>  	unsigned int p_space;
>  
> @@ -1030,7 +1030,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
>  			       splice_direct_actor *actor)
>  {
>  	struct pipe_inode_info *pipe;
> -	long ret, bytes;
> +	size_t ret, bytes;
        ^^^^ ssize_t here?

>  	size_t len;
>  	int i, flags, more;
>  
...
> @@ -1962,7 +1962,7 @@ static int link_pipe(struct pipe_inode_info *ipipe,
>   * The 'flags' used are the SPLICE_F_* variants, currently the only
>   * applicable one is SPLICE_F_NONBLOCK.
>   */

Actually link_pipe() should also return ssize_t instead of int, shouldn't
it?

> -long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
> +ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags)
>  {
>  	struct pipe_inode_info *ipipe = get_pipe_info(in, true);
>  	struct pipe_inode_info *opipe = get_pipe_info(out, true);

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper
  2023-12-10 14:18 ` [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper Amir Goldstein
@ 2023-12-11 14:45   ` Jan Kara
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kara @ 2023-12-11 14:45 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Christian Brauner, Jan Kara, Jeff Layton, Josef Bacik,
	Christoph Hellwig, David Howells, Jens Axboe, Miklos Szeredi,
	Al Viro, linux-fsdevel

On Sun 10-12-23 16:18:58, Amir Goldstein wrote:
> generic_copy_file_range() is just a wrapper around splice_file_range(),
> which caps the maximum copy length.
> 
> The only caller of splice_file_range(), namely __ceph_copy_file_range()
> is already ready to cope with short copy.
> 
> Move the length capping into splice_file_range() and replace the exported
> symbol generic_copy_file_range() with a simple inline helper.
> 
> Suggested-by: Christoph Hellwig <hch@lst.de>
> Link: https://lore.kernel.org/linux-fsdevel/20231204083849.GC32438@lst.de/
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH v2 1/5] splice: return type ssize_t from all helpers
  2023-12-11 14:39   ` Jan Kara
@ 2023-12-11 15:17     ` Amir Goldstein
  0 siblings, 0 replies; 11+ messages in thread
From: Amir Goldstein @ 2023-12-11 15:17 UTC (permalink / raw)
  To: Jan Kara
  Cc: Christian Brauner, Jeff Layton, Josef Bacik, Christoph Hellwig,
	David Howells, Jens Axboe, Miklos Szeredi, Al Viro, linux-fsdevel

On Mon, Dec 11, 2023 at 4:39 PM Jan Kara <jack@suse.cz> wrote:
>
> On Sun 10-12-23 16:18:57, Amir Goldstein wrote:
> > Not sure why some splice helpers return long, maybe historic reasons.
> > Change them all to return ssize_t to conform to the splice methods and
> > to the rest of the helpers.
> >
> > Suggested-by: Christian Brauner <brauner@kernel.org>
> > Link: https://lore.kernel.org/r/20231208-horchen-helium-d3ec1535ede5@brauner/
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
>
> > @@ -955,9 +955,9 @@ static void do_splice_eof(struct splice_desc *sd)
> >   * Callers already called rw_verify_area() on the entire range.
> >   * No need to call it for sub ranges.
> >   */
> > -static long do_splice_read(struct file *in, loff_t *ppos,
> > -                        struct pipe_inode_info *pipe, size_t len,
> > -                        unsigned int flags)
> > +static size_t do_splice_read(struct file *in, loff_t *ppos,
>           ^^^ ssize_t here?
>
> > +                          struct pipe_inode_info *pipe, size_t len,
> > +                          unsigned int flags)
> >  {
> >       unsigned int p_space;
> >
> > @@ -1030,7 +1030,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
> >                              splice_direct_actor *actor)
> >  {
> >       struct pipe_inode_info *pipe;
> > -     long ret, bytes;
> > +     size_t ret, bytes;
>         ^^^^ ssize_t here?
>

Yap, I had more than one miss...

> >       size_t len;
> >       int i, flags, more;
> >
> ...
> > @@ -1962,7 +1962,7 @@ static int link_pipe(struct pipe_inode_info *ipipe,
> >   * The 'flags' used are the SPLICE_F_* variants, currently the only
> >   * applicable one is SPLICE_F_NONBLOCK.
> >   */
>
> Actually link_pipe() should also return ssize_t instead of int, shouldn't
> it?

Wouldn't hurt.
I also see that I missed the vmsplice_ helpers.

I see v3 in my future...

Thanks,
Amir.

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

* Re: [PATCH v2 5/5] fsnotify: optionally pass access range in file permission hooks
  2023-12-10 14:19 ` [PATCH v2 5/5] fsnotify: optionally pass access range in file " Amir Goldstein
@ 2023-12-11 15:20   ` Jan Kara
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kara @ 2023-12-11 15:20 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Christian Brauner, Jan Kara, Jeff Layton, Josef Bacik,
	Christoph Hellwig, David Howells, Jens Axboe, Miklos Szeredi,
	Al Viro, linux-fsdevel

On Sun 10-12-23 16:19:01, Amir Goldstein wrote:
> In preparation for pre-content permission events with file access range,
> move fsnotify_file_perm() hook out of security_file_permission() and into
> the callers.
> 
> Callers that have the access range information call the new hook
> fsnotify_file_area_perm() with the access range.
> 
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

end of thread, other threads:[~2023-12-11 15:20 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-10 14:18 [PATCH v2 0/5] Prepare for fsnotify pre-content permission events Amir Goldstein
2023-12-10 14:18 ` [PATCH v2 1/5] splice: return type ssize_t from all helpers Amir Goldstein
2023-12-11  6:57   ` Amir Goldstein
2023-12-11 14:39   ` Jan Kara
2023-12-11 15:17     ` Amir Goldstein
2023-12-10 14:18 ` [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper Amir Goldstein
2023-12-11 14:45   ` Jan Kara
2023-12-10 14:18 ` [PATCH v2 3/5] fsnotify: split fsnotify_perm() into two hooks Amir Goldstein
2023-12-10 14:19 ` [PATCH v2 4/5] fsnotify: assert that file_start_write() is not held in permission hooks Amir Goldstein
2023-12-10 14:19 ` [PATCH v2 5/5] fsnotify: optionally pass access range in file " Amir Goldstein
2023-12-11 15:20   ` Jan Kara

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 read-only IMAP folder(s) and NNTP newsgroup(s).