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.

fs: move permission hook out of do_iter_write()

In many of the vfs helpers, the rw_verity_area() checks are called before
taking sb_start_write(), making them "start-write-safe".
do_iter_write() is an exception to this rule.

do_iter_write() has two callers - vfs_iter_write() and vfs_writev().
Move rw_verify_area() and other checks from do_iter_write() out to
its callers to make them "start-write-safe".

Move also the fsnotify_modify() hook to align with similar pattern
used in vfs_write() and other vfs helpers.

This is needed for fanotify "pre content" events.

Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231122122715.2561213-12-amir73il@gmail.com
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Amir Goldstein and committed by
Christian Brauner
1c8aa833 269aed70

+48 -38
+48 -38
fs/read_write.c
··· 838 838 } 839 839 EXPORT_SYMBOL(vfs_iter_read); 840 840 841 - static ssize_t do_iter_write(struct file *file, struct iov_iter *iter, 842 - loff_t *pos, rwf_t flags) 843 - { 844 - size_t tot_len; 845 - ssize_t ret = 0; 846 - 847 - if (!(file->f_mode & FMODE_WRITE)) 848 - return -EBADF; 849 - if (!(file->f_mode & FMODE_CAN_WRITE)) 850 - return -EINVAL; 851 - 852 - tot_len = iov_iter_count(iter); 853 - if (!tot_len) 854 - return 0; 855 - ret = rw_verify_area(WRITE, file, pos, tot_len); 856 - if (ret < 0) 857 - return ret; 858 - 859 - if (file->f_op->write_iter) 860 - ret = do_iter_readv_writev(file, iter, pos, WRITE, flags); 861 - else 862 - ret = do_loop_readv_writev(file, iter, pos, WRITE, flags); 863 - if (ret > 0) 864 - fsnotify_modify(file); 865 - return ret; 866 - } 867 - 868 841 ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb, 869 842 struct iov_iter *iter) 870 843 { ··· 869 896 ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos, 870 897 rwf_t flags) 871 898 { 872 - int ret; 899 + size_t tot_len; 900 + ssize_t ret; 873 901 902 + if (!(file->f_mode & FMODE_WRITE)) 903 + return -EBADF; 904 + if (!(file->f_mode & FMODE_CAN_WRITE)) 905 + return -EINVAL; 874 906 if (!file->f_op->write_iter) 875 907 return -EINVAL; 876 908 909 + tot_len = iov_iter_count(iter); 910 + if (!tot_len) 911 + return 0; 912 + 913 + ret = rw_verify_area(WRITE, file, ppos, tot_len); 914 + if (ret < 0) 915 + return ret; 916 + 877 917 file_start_write(file); 878 - ret = do_iter_write(file, iter, ppos, flags); 918 + ret = do_iter_readv_writev(file, iter, ppos, WRITE, flags); 919 + if (ret > 0) 920 + fsnotify_modify(file); 879 921 file_end_write(file); 880 922 881 923 return ret; ··· 915 927 } 916 928 917 929 static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, 918 - unsigned long vlen, loff_t *pos, rwf_t flags) 930 + unsigned long vlen, loff_t *pos, rwf_t flags) 919 931 { 920 932 struct iovec iovstack[UIO_FASTIOV]; 921 933 struct iovec *iov = iovstack; 922 934 struct iov_iter iter; 923 - ssize_t ret; 935 + size_t tot_len; 936 + ssize_t ret = 0; 924 937 925 - ret = import_iovec(ITER_SOURCE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); 926 - if (ret >= 0) { 927 - file_start_write(file); 928 - ret = do_iter_write(file, &iter, pos, flags); 929 - file_end_write(file); 930 - kfree(iov); 931 - } 938 + if (!(file->f_mode & FMODE_WRITE)) 939 + return -EBADF; 940 + if (!(file->f_mode & FMODE_CAN_WRITE)) 941 + return -EINVAL; 942 + 943 + ret = import_iovec(ITER_SOURCE, vec, vlen, ARRAY_SIZE(iovstack), &iov, 944 + &iter); 945 + if (ret < 0) 946 + return ret; 947 + 948 + tot_len = iov_iter_count(&iter); 949 + if (!tot_len) 950 + goto out; 951 + 952 + ret = rw_verify_area(WRITE, file, pos, tot_len); 953 + if (ret < 0) 954 + goto out; 955 + 956 + file_start_write(file); 957 + if (file->f_op->write_iter) 958 + ret = do_iter_readv_writev(file, &iter, pos, WRITE, flags); 959 + else 960 + ret = do_loop_readv_writev(file, &iter, pos, WRITE, flags); 961 + if (ret > 0) 962 + fsnotify_modify(file); 963 + file_end_write(file); 964 + out: 965 + kfree(iov); 932 966 return ret; 933 967 } 934 968