| From 31070f6ccec09f3bd4f1e28cd1e592fa4f3ba0b6 Mon Sep 17 00:00:00 2001 |
| From: Chirantan Ekbote <chirantan@chromium.org> |
| Date: Tue, 14 Jul 2020 19:26:39 +0900 |
| Subject: fuse: Fix parameter for FS_IOC_{GET,SET}FLAGS |
| |
| From: Chirantan Ekbote <chirantan@chromium.org> |
| |
| commit 31070f6ccec09f3bd4f1e28cd1e592fa4f3ba0b6 upstream. |
| |
| The ioctl encoding for this parameter is a long but the documentation says |
| it should be an int and the kernel drivers expect it to be an int. If the |
| fuse driver treats this as a long it might end up scribbling over the stack |
| of a userspace process that only allocated enough space for an int. |
| |
| This was previously discussed in [1] and a patch for fuse was proposed in |
| [2]. From what I can tell the patch in [2] was nacked in favor of adding |
| new, "fixed" ioctls and using those from userspace. However there is still |
| no "fixed" version of these ioctls and the fact is that it's sometimes |
| infeasible to change all userspace to use the new one. |
| |
| Handling the ioctls specially in the fuse driver seems like the most |
| pragmatic way for fuse servers to support them without causing crashes in |
| userspace applications that call them. |
| |
| [1]: https://lore.kernel.org/linux-fsdevel/20131126200559.GH20559@hall.aurel32.net/T/ |
| [2]: https://sourceforge.net/p/fuse/mailman/message/31771759/ |
| |
| Signed-off-by: Chirantan Ekbote <chirantan@chromium.org> |
| Fixes: 59efec7b9039 ("fuse: implement ioctl support") |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fuse/file.c | 12 +++++++++++- |
| 1 file changed, 11 insertions(+), 1 deletion(-) |
| |
| --- a/fs/fuse/file.c |
| +++ b/fs/fuse/file.c |
| @@ -17,6 +17,7 @@ |
| #include <linux/swap.h> |
| #include <linux/falloc.h> |
| #include <linux/uio.h> |
| +#include <linux/fs.h> |
| |
| static const struct file_operations fuse_direct_io_file_operations; |
| |
| @@ -2520,7 +2521,16 @@ long fuse_do_ioctl(struct file *file, un |
| struct iovec *iov = iov_page; |
| |
| iov->iov_base = (void __user *)arg; |
| - iov->iov_len = _IOC_SIZE(cmd); |
| + |
| + switch (cmd) { |
| + case FS_IOC_GETFLAGS: |
| + case FS_IOC_SETFLAGS: |
| + iov->iov_len = sizeof(int); |
| + break; |
| + default: |
| + iov->iov_len = _IOC_SIZE(cmd); |
| + break; |
| + } |
| |
| if (_IOC_DIR(cmd) & _IOC_WRITE) { |
| in_iov = iov; |