Commit ce6d8309 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by sanglipeng
Browse files

fuse: lock inode unconditionally in fuse_fallocate()

stable inclusion
from stable-v5.10.157
commit 4801672fb076d546c67504ec9810a3a467e91768
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7MU59

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4801672fb076d546c67504ec9810a3a467e91768



--------------------------------

commit 44361e8c 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: 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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent 3415cc1e
Loading
Loading
Loading
Loading
+16 −20
Original line number Diff line number Diff line
@@ -3290,10 +3290,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;
@@ -3301,7 +3300,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) {
		down_write(&fi->i_mmap_sem);
@@ -3317,7 +3315,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)) {
@@ -3366,7 +3363,6 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
	if (block_faults)
		up_write(&fi->i_mmap_sem);

	if (lock_inode)
	inode_unlock(inode);

	fuse_flush_time_update(inode);