Commit 44361e8c authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

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: default avatarPengfei Xu <pengfei.xu@intel.com>
Reported-and-tested-by: default avatar <syzbot+462da39f0667b357c4b6@syzkaller.appspotmail.com>
Fixes: 4a6f278d ("fuse: add file_modified() to fallocate")
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent eb708140
Loading
Loading
Loading
Loading
+16 −21
Original line number Diff line number Diff line
@@ -2963,11 +2963,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 |
				    FALLOC_FL_ZERO_RANGE));

	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 | FALLOC_FL_ZERO_RANGE)));

	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
		     FALLOC_FL_ZERO_RANGE))
@@ -2976,7 +2974,6 @@ 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) {
		filemap_invalidate_lock(inode->i_mapping);
@@ -2992,7 +2989,6 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
		if (err)
			goto out;
	}
	}

	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
	    offset + length > i_size_read(inode)) {
@@ -3039,7 +3035,6 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
	if (block_faults)
		filemap_invalidate_unlock(inode->i_mapping);

	if (lock_inode)
	inode_unlock(inode);

	fuse_flush_time_update(inode);