fuse: ioctl: translate ENOSYS in outarg
commit6a567e920f
upstream. Fuse shouldn't return ENOSYS from its ioctl implementation. If userspace responds with ENOSYS it should be translated to ENOTTY. There are two ways to return an error from the IOCTL request: - fuse_out_header.error - fuse_ioctl_out.result Commit02c0cab8e7
("fuse: ioctl: translate ENOSYS") already fixed this issue for the first case, but missed the second case. This patch fixes the second case. Reported-by: Jonathan Katz <jkatz@eitmlabs.org> Closes: https://lore.kernel.org/all/CALKgVmcC1VUV_gJVq70n--omMJZUb4HSh_FqvLTHgNBc+HCLFQ@mail.gmail.com/ Fixes:02c0cab8e7
("fuse: ioctl: translate ENOSYS") Cc: <stable@vger.kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c35ea60619
commit
c828e913c8
|
@ -9,14 +9,23 @@
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/fileattr.h>
|
#include <linux/fileattr.h>
|
||||||
|
|
||||||
static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args)
|
static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
|
||||||
|
struct fuse_ioctl_out *outarg)
|
||||||
{
|
{
|
||||||
ssize_t ret = fuse_simple_request(fm, args);
|
ssize_t ret;
|
||||||
|
|
||||||
|
args->out_args[0].size = sizeof(*outarg);
|
||||||
|
args->out_args[0].value = outarg;
|
||||||
|
|
||||||
|
ret = fuse_simple_request(fm, args);
|
||||||
|
|
||||||
/* Translate ENOSYS, which shouldn't be returned from fs */
|
/* Translate ENOSYS, which shouldn't be returned from fs */
|
||||||
if (ret == -ENOSYS)
|
if (ret == -ENOSYS)
|
||||||
ret = -ENOTTY;
|
ret = -ENOTTY;
|
||||||
|
|
||||||
|
if (ret >= 0 && outarg->result == -ENOSYS)
|
||||||
|
outarg->result = -ENOTTY;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,13 +273,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
ap.args.out_numargs = 2;
|
ap.args.out_numargs = 2;
|
||||||
ap.args.out_args[0].size = sizeof(outarg);
|
|
||||||
ap.args.out_args[0].value = &outarg;
|
|
||||||
ap.args.out_args[1].size = out_size;
|
ap.args.out_args[1].size = out_size;
|
||||||
ap.args.out_pages = true;
|
ap.args.out_pages = true;
|
||||||
ap.args.out_argvar = true;
|
ap.args.out_argvar = true;
|
||||||
|
|
||||||
transferred = fuse_send_ioctl(fm, &ap.args);
|
transferred = fuse_send_ioctl(fm, &ap.args, &outarg);
|
||||||
err = transferred;
|
err = transferred;
|
||||||
if (transferred < 0)
|
if (transferred < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -399,12 +406,10 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff,
|
||||||
args.in_args[1].size = inarg.in_size;
|
args.in_args[1].size = inarg.in_size;
|
||||||
args.in_args[1].value = ptr;
|
args.in_args[1].value = ptr;
|
||||||
args.out_numargs = 2;
|
args.out_numargs = 2;
|
||||||
args.out_args[0].size = sizeof(outarg);
|
|
||||||
args.out_args[0].value = &outarg;
|
|
||||||
args.out_args[1].size = inarg.out_size;
|
args.out_args[1].size = inarg.out_size;
|
||||||
args.out_args[1].value = ptr;
|
args.out_args[1].value = ptr;
|
||||||
|
|
||||||
err = fuse_send_ioctl(fm, &args);
|
err = fuse_send_ioctl(fm, &args, &outarg);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (outarg.result < 0)
|
if (outarg.result < 0)
|
||||||
err = outarg.result;
|
err = outarg.result;
|
||||||
|
|
Loading…
Reference in New Issue