]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: lock inode unconditionally in fuse_fallocate()
authorMiklos Szeredi <mszeredi@redhat.com>
Wed, 23 Nov 2022 08:10:42 +0000 (09:10 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Dec 2022 16:40:07 +0000 (17:40 +0100)
commit 44361e8cf9ddb23f17bdcc40ca944abf32e83e79 upstream.

file_modified() must be called with inode lock held.  fuse_fallocate()
didn't lock the inode in case of just FALLOC_KEEP_SIZE flags value, which
resulted in a kernel Warning in notify_change().

Lock the inode unconditionally, like all other fallocate implementations
do.

Reported-by: Pengfei Xu <pengfei.xu@intel.com>
Reported-and-tested-by: syzbot+462da39f0667b357c4b6@syzkaller.appspotmail.com
Fixes: 4a6f278d4827 ("fuse: add file_modified() to fallocate")
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/fuse/file.c

index 253308fcb0478e24763eaa7daaeaac3c36dce761..504389568dac58ae0fde6e83115e85ff152404de 100644 (file)
@@ -3275,10 +3275,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                .mode = mode
        };
        int err;
-       bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
-                          (mode & FALLOC_FL_PUNCH_HOLE);
-
-       bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
+       bool block_faults = FUSE_IS_DAX(inode) &&
+               (!(mode & FALLOC_FL_KEEP_SIZE) ||
+                (mode & FALLOC_FL_PUNCH_HOLE));
 
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
@@ -3286,22 +3285,20 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        if (fm->fc->no_fallocate)
                return -EOPNOTSUPP;
 
-       if (lock_inode) {
-               inode_lock(inode);
-               if (block_faults) {
-                       down_write(&fi->i_mmap_sem);
-                       err = fuse_dax_break_layouts(inode, 0, 0);
-                       if (err)
-                               goto out;
-               }
+       inode_lock(inode);
+       if (block_faults) {
+               down_write(&fi->i_mmap_sem);
+               err = fuse_dax_break_layouts(inode, 0, 0);
+               if (err)
+                       goto out;
+       }
 
-               if (mode & FALLOC_FL_PUNCH_HOLE) {
-                       loff_t endbyte = offset + length - 1;
+       if (mode & FALLOC_FL_PUNCH_HOLE) {
+               loff_t endbyte = offset + length - 1;
 
-                       err = fuse_writeback_range(inode, offset, endbyte);
-                       if (err)
-                               goto out;
-               }
+               err = fuse_writeback_range(inode, offset, endbyte);
+               if (err)
+                       goto out;
        }
 
        if (!(mode & FALLOC_FL_KEEP_SIZE) &&
@@ -3351,8 +3348,7 @@ out:
        if (block_faults)
                up_write(&fi->i_mmap_sem);
 
-       if (lock_inode)
-               inode_unlock(inode);
+       inode_unlock(inode);
 
        fuse_flush_time_update(inode);