]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fuse: fuse_dev_ioctl_clone() should wait for device file to be initialized
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 2 Apr 2026 18:19:55 +0000 (20:19 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 2 Apr 2026 18:29:34 +0000 (20:29 +0200)
Use fuse_get_dev() not __fuse_get_dev() on the old fd, since in the case of
synchronous INIT the caller will want to wait for the device file to be
available for cloning, just like I/O wants to wait instead of returning an
error.

Fixes: dfb84c330794 ("fuse: allow synchronous FUSE_INIT")
Cc: stable@vger.kernel.org # v6.18
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c

index b212565a78cf4760f7df0e14e04a210d27d81bf9..8d5bab05adf4971b918f3a095d59da55f2399f8c 100644 (file)
@@ -2597,9 +2597,8 @@ static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
 
 static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
 {
-       int res;
        int oldfd;
-       struct fuse_dev *fud = NULL;
+       struct fuse_dev *fud;
 
        if (get_user(oldfd, argp))
                return -EFAULT;
@@ -2612,17 +2611,15 @@ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
         * Check against file->f_op because CUSE
         * uses the same ioctl handler.
         */
-       if (fd_file(f)->f_op == file->f_op)
-               fud = __fuse_get_dev(fd_file(f));
+       if (fd_file(f)->f_op != file->f_op)
+               return -EINVAL;
 
-       res = -EINVAL;
-       if (fud) {
-               mutex_lock(&fuse_mutex);
-               res = fuse_device_clone(fud->fc, file);
-               mutex_unlock(&fuse_mutex);
-       }
+       fud = fuse_get_dev(fd_file(f));
+       if (IS_ERR(fud))
+               return PTR_ERR(fud);
 
-       return res;
+       guard(mutex)(&fuse_mutex);
+       return fuse_device_clone(fud->fc, file);
 }
 
 static long fuse_dev_ioctl_backing_open(struct file *file,