Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fuse: ioctl: translate ENOSYS in outarg

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

Commit 02c0cab8e734 ("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: 02c0cab8e734 ("fuse: ioctl: translate ENOSYS")
Cc: <stable@vger.kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

+13 -8
+13 -8
fs/fuse/ioctl.c
··· 9 9 #include <linux/compat.h> 10 10 #include <linux/fileattr.h> 11 11 12 - static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args) 12 + static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args, 13 + struct fuse_ioctl_out *outarg) 13 14 { 14 - ssize_t ret = fuse_simple_request(fm, args); 15 + ssize_t ret; 16 + 17 + args->out_args[0].size = sizeof(*outarg); 18 + args->out_args[0].value = outarg; 19 + 20 + ret = fuse_simple_request(fm, args); 15 21 16 22 /* Translate ENOSYS, which shouldn't be returned from fs */ 17 23 if (ret == -ENOSYS) 18 24 ret = -ENOTTY; 25 + 26 + if (ret >= 0 && outarg->result == -ENOSYS) 27 + outarg->result = -ENOTTY; 19 28 20 29 return ret; 21 30 } ··· 273 264 } 274 265 275 266 ap.args.out_numargs = 2; 276 - ap.args.out_args[0].size = sizeof(outarg); 277 - ap.args.out_args[0].value = &outarg; 278 267 ap.args.out_args[1].size = out_size; 279 268 ap.args.out_pages = true; 280 269 ap.args.out_argvar = true; 281 270 282 - transferred = fuse_send_ioctl(fm, &ap.args); 271 + transferred = fuse_send_ioctl(fm, &ap.args, &outarg); 283 272 err = transferred; 284 273 if (transferred < 0) 285 274 goto out; ··· 406 399 args.in_args[1].size = inarg.in_size; 407 400 args.in_args[1].value = ptr; 408 401 args.out_numargs = 2; 409 - args.out_args[0].size = sizeof(outarg); 410 - args.out_args[0].value = &outarg; 411 402 args.out_args[1].size = inarg.out_size; 412 403 args.out_args[1].value = ptr; 413 404 414 - err = fuse_send_ioctl(fm, &args); 405 + err = fuse_send_ioctl(fm, &args, &outarg); 415 406 if (!err) { 416 407 if (outarg.result < 0) 417 408 err = outarg.result;