diff options
author | Arnd Bergmann <arnd@arndb.de> | 2020-02-07 17:55:48 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2020-02-08 18:02:54 +0100 |
commit | 0a061743af93f472687b8c69b0d539d1f12f3fd2 (patch) | |
tree | 3170c2624e96172f2dffa1622bdab8369e88a83b /fs/ioctl.c | |
parent | 77b9040195dea3fcddf19e136c9e99a501351778 (diff) | |
download | lwn-0a061743af93f472687b8c69b0d539d1f12f3fd2.tar.gz lwn-0a061743af93f472687b8c69b0d539d1f12f3fd2.zip |
compat_ioctl: fix FIONREAD on devices
My final cleanup patch for sys_compat_ioctl() introduced a regression on
the FIONREAD ioctl command, which is used for both regular and special
files, but only works on regular files after my patch, as I had missed
the warning that Al Viro put into a comment right above it.
Change it back so it can work on any file again by moving the implementation
to do_vfs_ioctl() instead.
Fixes: 77b9040195de ("compat_ioctl: simplify the implementation")
Reported-and-tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
Reported-and-tested-by: youling257 <youling257@gmail.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r-- | fs/ioctl.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index 7c9a5df5a597..5152c98cfc30 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -523,13 +523,9 @@ static int compat_ioctl_preallocate(struct file *file, int mode, static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p) { - struct inode *inode = file_inode(filp); - switch (cmd) { case FIBMAP: return ioctl_fibmap(filp, p); - case FIONREAD: - return put_user(i_size_read(inode) - filp->f_pos, p); case FS_IOC_RESVSP: case FS_IOC_RESVSP64: return ioctl_preallocate(filp, 0, p); @@ -721,6 +717,13 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd, case FIDEDUPERANGE: return ioctl_file_dedupe_range(filp, argp); + case FIONREAD: + if (!S_ISREG(inode->i_mode)) + return vfs_ioctl(filp, cmd, arg); + + return put_user(i_size_read(inode) - filp->f_pos, + (int __user *)argp); + default: if (S_ISREG(inode->i_mode)) return file_ioctl(filp, cmd, argp); |