diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2026-04-02 21:19:55 +0300 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2026-04-02 21:29:34 +0300 |
| commit | da6fcc6dbddbef80e603d2f0c1554a9f2ac03742 (patch) | |
| tree | 3626336a0d27cdb57053e62906ddb64dd53e8fbe | |
| parent | aff12041b4b2f4f2c164a0cf1b9688408515d036 (diff) | |
| download | linux-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.c | 19 |
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, |
