Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

splice: move permission hook out of splice_direct_to_actor()

vfs_splice_read() has a permission hook inside rw_verify_area() and
it is called from do_splice_direct() -> splice_direct_to_actor().

The callers of do_splice_direct() (e.g. vfs_copy_file_range()) already
call rw_verify_area() for the entire range, but the other caller of
splice_direct_to_actor() (nfsd) does not.

Add the rw_verify_area() checks in nfsd_splice_read() and use a
variant of vfs_splice_read() without rw_verify_area() check in
splice_direct_to_actor() to avoid the redundant rw_verify_area() checks.

This is needed for fanotify "pre content" events.

Acked-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231122122715.2561213-4-amir73il@gmail.com
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Amir Goldstein and committed by
Christian Brauner
feebea75 2a33e2dd

+39 -24
+4 -1
fs/nfsd/vfs.c
··· 1046 1046 ssize_t host_err; 1047 1047 1048 1048 trace_nfsd_read_splice(rqstp, fhp, offset, *count); 1049 - host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); 1049 + host_err = rw_verify_area(READ, file, &offset, *count); 1050 + if (!host_err) 1051 + host_err = splice_direct_to_actor(file, &sd, 1052 + nfsd_direct_splice_actor); 1050 1053 return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err); 1051 1054 } 1052 1055
+35 -23
fs/splice.c
··· 944 944 sd->splice_eof(sd); 945 945 } 946 946 947 + /* 948 + * Callers already called rw_verify_area() on the entire range. 949 + * No need to call it for sub ranges. 950 + */ 951 + static long do_splice_read(struct file *in, loff_t *ppos, 952 + struct pipe_inode_info *pipe, size_t len, 953 + unsigned int flags) 954 + { 955 + unsigned int p_space; 956 + 957 + if (unlikely(!(in->f_mode & FMODE_READ))) 958 + return -EBADF; 959 + if (!len) 960 + return 0; 961 + 962 + /* Don't try to read more the pipe has space for. */ 963 + p_space = pipe->max_usage - pipe_occupancy(pipe->head, pipe->tail); 964 + len = min_t(size_t, len, p_space << PAGE_SHIFT); 965 + 966 + if (unlikely(len > MAX_RW_COUNT)) 967 + len = MAX_RW_COUNT; 968 + 969 + if (unlikely(!in->f_op->splice_read)) 970 + return warn_unsupported(in, "read"); 971 + /* 972 + * O_DIRECT and DAX don't deal with the pagecache, so we allocate a 973 + * buffer, copy into it and splice that into the pipe. 974 + */ 975 + if ((in->f_flags & O_DIRECT) || IS_DAX(in->f_mapping->host)) 976 + return copy_splice_read(in, ppos, pipe, len, flags); 977 + return in->f_op->splice_read(in, ppos, pipe, len, flags); 978 + } 979 + 947 980 /** 948 981 * vfs_splice_read - Read data from a file and splice it into a pipe 949 982 * @in: File to splice from ··· 996 963 struct pipe_inode_info *pipe, size_t len, 997 964 unsigned int flags) 998 965 { 999 - unsigned int p_space; 1000 966 int ret; 1001 - 1002 - if (unlikely(!(in->f_mode & FMODE_READ))) 1003 - return -EBADF; 1004 - if (!len) 1005 - return 0; 1006 - 1007 - /* Don't try to read more the pipe has space for. */ 1008 - p_space = pipe->max_usage - pipe_occupancy(pipe->head, pipe->tail); 1009 - len = min_t(size_t, len, p_space << PAGE_SHIFT); 1010 967 1011 968 ret = rw_verify_area(READ, in, ppos, len); 1012 969 if (unlikely(ret < 0)) 1013 970 return ret; 1014 971 1015 - if (unlikely(len > MAX_RW_COUNT)) 1016 - len = MAX_RW_COUNT; 1017 - 1018 - if (unlikely(!in->f_op->splice_read)) 1019 - return warn_unsupported(in, "read"); 1020 - /* 1021 - * O_DIRECT and DAX don't deal with the pagecache, so we allocate a 1022 - * buffer, copy into it and splice that into the pipe. 1023 - */ 1024 - if ((in->f_flags & O_DIRECT) || IS_DAX(in->f_mapping->host)) 1025 - return copy_splice_read(in, ppos, pipe, len, flags); 1026 - return in->f_op->splice_read(in, ppos, pipe, len, flags); 972 + return do_splice_read(in, ppos, pipe, len, flags); 1027 973 } 1028 974 EXPORT_SYMBOL_GPL(vfs_splice_read); 1029 975 ··· 1078 1066 size_t read_len; 1079 1067 loff_t pos = sd->pos, prev_pos = pos; 1080 1068 1081 - ret = vfs_splice_read(in, &pos, pipe, len, flags); 1069 + ret = do_splice_read(in, &pos, pipe, len, flags); 1082 1070 if (unlikely(ret <= 0)) 1083 1071 goto read_failure; 1084 1072