diff options
-rw-r--r-- | queue-6.15/fs-add-s_anon_inode.patch | 142 | ||||
-rw-r--r-- | queue-6.15/series | 1 |
2 files changed, 143 insertions, 0 deletions
diff --git a/queue-6.15/fs-add-s_anon_inode.patch b/queue-6.15/fs-add-s_anon_inode.patch new file mode 100644 index 0000000000..2124ff345a --- /dev/null +++ b/queue-6.15/fs-add-s_anon_inode.patch @@ -0,0 +1,142 @@ +From 19bbfe7b5fcc04d8711e8e1352acc77c1a5c3955 Mon Sep 17 00:00:00 2001 +From: Christian Brauner <brauner@kernel.org> +Date: Mon, 21 Apr 2025 10:27:40 +0200 +Subject: fs: add S_ANON_INODE + +From: Christian Brauner <brauner@kernel.org> + +commit 19bbfe7b5fcc04d8711e8e1352acc77c1a5c3955 upstream. + +This makes it easy to detect proper anonymous inodes and to ensure that +we can detect them in codepaths such as readahead(). + +Readahead on anonymous inodes didn't work because they didn't have a +proper mode. Now that they have we need to retain EINVAL being returned +otherwise LTP will fail. + +We also need to ensure that ioctls aren't simply fired like they are for +regular files so things like inotify inodes continue to correctly call +their own ioctl handlers as in [1]. + +Reported-by: Xilin Wu <sophon@radxa.com> +Link: https://lore.kernel.org/3A9139D5CD543962+89831381-31b9-4392-87ec-a84a5b3507d8@radxa.com [1] +Link: https://lore.kernel.org/7a1a7076-ff6b-4cb0-94e7-7218a0a44028@sirena.org.uk +Signed-off-by: Christian Brauner <brauner@kernel.org> +Cc: "Barry K. Nathan" <barryn@pobox.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + fs/ioctl.c | 7 ++++--- + fs/libfs.c | 2 +- + fs/pidfs.c | 2 +- + include/linux/fs.h | 2 ++ + mm/readahead.c | 20 ++++++++++++++++---- + 5 files changed, 24 insertions(+), 9 deletions(-) + +--- a/fs/ioctl.c ++++ b/fs/ioctl.c +@@ -821,7 +821,8 @@ static int do_vfs_ioctl(struct file *fil + return ioctl_fioasync(fd, filp, argp); + + case FIOQSIZE: +- if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || ++ if (S_ISDIR(inode->i_mode) || ++ (S_ISREG(inode->i_mode) && !IS_ANON_FILE(inode)) || + S_ISLNK(inode->i_mode)) { + loff_t res = inode_get_bytes(inode); + return copy_to_user(argp, &res, sizeof(res)) ? +@@ -856,7 +857,7 @@ static int do_vfs_ioctl(struct file *fil + return ioctl_file_dedupe_range(filp, argp); + + case FIONREAD: +- if (!S_ISREG(inode->i_mode)) ++ if (!S_ISREG(inode->i_mode) || IS_ANON_FILE(inode)) + return vfs_ioctl(filp, cmd, arg); + + return put_user(i_size_read(inode) - filp->f_pos, +@@ -881,7 +882,7 @@ static int do_vfs_ioctl(struct file *fil + return ioctl_get_fs_sysfs_path(filp, argp); + + default: +- if (S_ISREG(inode->i_mode)) ++ if (S_ISREG(inode->i_mode) && !IS_ANON_FILE(inode)) + return file_ioctl(filp, cmd, argp); + break; + } +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -1656,7 +1656,7 @@ struct inode *alloc_anon_inode(struct su + inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; + inode->i_uid = current_fsuid(); + inode->i_gid = current_fsgid(); +- inode->i_flags |= S_PRIVATE; ++ inode->i_flags |= S_PRIVATE | S_ANON_INODE; + simple_inode_init_ts(inode); + return inode; + } +--- a/fs/pidfs.c ++++ b/fs/pidfs.c +@@ -826,7 +826,7 @@ static int pidfs_init_inode(struct inode + const struct pid *pid = data; + + inode->i_private = data; +- inode->i_flags |= S_PRIVATE; ++ inode->i_flags |= S_PRIVATE | S_ANON_INODE; + inode->i_mode |= S_IRWXU; + inode->i_op = &pidfs_inode_operations; + inode->i_fop = &pidfs_file_operations; +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2344,6 +2344,7 @@ struct super_operations { + #define S_CASEFOLD (1 << 15) /* Casefolded file */ + #define S_VERITY (1 << 16) /* Verity file (using fs/verity/) */ + #define S_KERNEL_FILE (1 << 17) /* File is in use by the kernel (eg. fs/cachefiles) */ ++#define S_ANON_INODE (1 << 19) /* Inode is an anonymous inode */ + + /* + * Note that nosuid etc flags are inode-specific: setting some file-system +@@ -2400,6 +2401,7 @@ static inline bool sb_rdonly(const struc + + #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \ + (inode)->i_rdev == WHITEOUT_DEV) ++#define IS_ANON_FILE(inode) ((inode)->i_flags & S_ANON_INODE) + + static inline bool HAS_UNMAPPED_ID(struct mnt_idmap *idmap, + struct inode *inode) +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -690,9 +690,15 @@ EXPORT_SYMBOL_GPL(page_cache_async_ra); + + ssize_t ksys_readahead(int fd, loff_t offset, size_t count) + { ++ struct file *file; ++ const struct inode *inode; ++ + CLASS(fd, f)(fd); ++ if (fd_empty(f)) ++ return -EBADF; + +- if (fd_empty(f) || !(fd_file(f)->f_mode & FMODE_READ)) ++ file = fd_file(f); ++ if (!(file->f_mode & FMODE_READ)) + return -EBADF; + + /* +@@ -700,9 +706,15 @@ ssize_t ksys_readahead(int fd, loff_t of + * that can execute readahead. If readahead is not possible + * on this file, then we must return -EINVAL. + */ +- if (!fd_file(f)->f_mapping || !fd_file(f)->f_mapping->a_ops || +- (!S_ISREG(file_inode(fd_file(f))->i_mode) && +- !S_ISBLK(file_inode(fd_file(f))->i_mode))) ++ if (!file->f_mapping) ++ return -EINVAL; ++ if (!file->f_mapping->a_ops) ++ return -EINVAL; ++ ++ inode = file_inode(file); ++ if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) ++ return -EINVAL; ++ if (IS_ANON_FILE(inode)) + return -EINVAL; + + return vfs_fadvise(fd_file(f), offset, count, POSIX_FADV_WILLNEED); diff --git a/queue-6.15/series b/queue-6.15/series index 6f39856164..1b2da1d690 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -33,6 +33,7 @@ wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch anon_inode-use-a-proper-mode-internally.patch anon_inode-explicitly-block-setattr.patch anon_inode-raise-sb_i_nodev-and-sb_i_noexec.patch +fs-add-s_anon_inode.patch wifi-ath11k-fix-rx-completion-meta-data-corruption.patch wifi-rtw88-usb-upload-the-firmware-in-bigger-chunks.patch wifi-ath11k-fix-ring-buffer-corruption.patch |