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

fuse: lock inode unconditionally in fuse_fallocate()

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>

+16 -21
+16 -21
fs/fuse/file.c
··· 2963 2963 .mode = mode 2964 2964 }; 2965 2965 int err; 2966 - bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) || 2967 - (mode & (FALLOC_FL_PUNCH_HOLE | 2968 - FALLOC_FL_ZERO_RANGE)); 2969 - 2970 - bool block_faults = FUSE_IS_DAX(inode) && lock_inode; 2966 + bool block_faults = FUSE_IS_DAX(inode) && 2967 + (!(mode & FALLOC_FL_KEEP_SIZE) || 2968 + (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))); 2971 2969 2972 2970 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | 2973 2971 FALLOC_FL_ZERO_RANGE)) ··· 2974 2976 if (fm->fc->no_fallocate) 2975 2977 return -EOPNOTSUPP; 2976 2978 2977 - if (lock_inode) { 2978 - inode_lock(inode); 2979 - if (block_faults) { 2980 - filemap_invalidate_lock(inode->i_mapping); 2981 - err = fuse_dax_break_layouts(inode, 0, 0); 2982 - if (err) 2983 - goto out; 2984 - } 2979 + inode_lock(inode); 2980 + if (block_faults) { 2981 + filemap_invalidate_lock(inode->i_mapping); 2982 + err = fuse_dax_break_layouts(inode, 0, 0); 2983 + if (err) 2984 + goto out; 2985 + } 2985 2986 2986 - if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) { 2987 - loff_t endbyte = offset + length - 1; 2987 + if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) { 2988 + loff_t endbyte = offset + length - 1; 2988 2989 2989 - err = fuse_writeback_range(inode, offset, endbyte); 2990 - if (err) 2991 - goto out; 2992 - } 2990 + err = fuse_writeback_range(inode, offset, endbyte); 2991 + if (err) 2992 + goto out; 2993 2993 } 2994 2994 2995 2995 if (!(mode & FALLOC_FL_KEEP_SIZE) && ··· 3035 3039 if (block_faults) 3036 3040 filemap_invalidate_unlock(inode->i_mapping); 3037 3041 3038 - if (lock_inode) 3039 - inode_unlock(inode); 3042 + inode_unlock(inode); 3040 3043 3041 3044 fuse_flush_time_update(inode); 3042 3045