mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
fs: add S_ANON_INODE
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>
This commit is contained in:
parent
c4044870ae
commit
19bbfe7b5f
5 changed files with 25 additions and 10 deletions
|
@ -821,7 +821,8 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
|
|||
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 *filp, unsigned int fd,
|
|||
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 *filp, unsigned int fd,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1656,7 +1656,7 @@ struct inode *alloc_anon_inode(struct super_block *s)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -804,7 +804,7 @@ static int pidfs_init_inode(struct inode *inode, void *data)
|
|||
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;
|
||||
|
|
|
@ -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 struct super_block *sb) { return sb->s_flags
|
|||
|
||||
#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)
|
||||
|
|
|
@ -690,9 +690,15 @@ EXPORT_SYMBOL_GPL(page_cache_async_ra);
|
|||
|
||||
ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
|
||||
{
|
||||
CLASS(fd, f)(fd);
|
||||
struct file *file;
|
||||
const struct inode *inode;
|
||||
|
||||
if (fd_empty(f) || !(fd_file(f)->f_mode & FMODE_READ))
|
||||
CLASS(fd, f)(fd);
|
||||
if (fd_empty(f))
|
||||
return -EBADF;
|
||||
|
||||
file = fd_file(f);
|
||||
if (!(file->f_mode & FMODE_READ))
|
||||
return -EBADF;
|
||||
|
||||
/*
|
||||
|
@ -700,9 +706,15 @@ ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
|
|||
* 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue