summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2026-04-02 21:19:55 +0300
committerMiklos Szeredi <mszeredi@redhat.com>2026-04-02 21:29:34 +0300
commitda6fcc6dbddbef80e603d2f0c1554a9f2ac03742 (patch)
tree3626336a0d27cdb57053e62906ddb64dd53e8fbe
parentaff12041b4b2f4f2c164a0cf1b9688408515d036 (diff)
downloadlinux-da6fcc6dbddbef80e603d2f0c1554a9f2ac03742.tar.xz
fuse: fuse_dev_ioctl_clone() should wait for device file to be initialized
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>
-rw-r--r--fs/fuse/dev.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index b212565a78cf..8d5bab05adf4 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -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,