Unverified Commit ec6164ad authored by Christian Brauner's avatar Christian Brauner
Browse files

Merge patch series "Fix for huge faults regression"

Amir Goldstein <amir73il@gmail.com> says:

The two Fix patches have been tested by Alex together and each one
independently.

I also verified that they pass the LTP inoityf/fanotify tests.

* patches from https://lore.kernel.org/r/20250203223205.861346-1-amir73il@gmail.com:
  fsnotify: disable pre-content and permission events by default
  fsnotify: disable notification by default for all pseudo files
  fsnotify: use accessor to set FMODE_NONOTIFY_*

Link: https://lore.kernel.org/r/20250203223205.861346-1-amir73il@gmail.com


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parents 2cc02059 711f9b8f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -798,7 +798,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
	nonseekable_open(inode, filp);

	/* We refuse fsnotify events on ptmx, since it's a shared resource */
	filp->f_mode |= FMODE_NONOTIFY;
	file_set_fsnotify_mode(filp, FMODE_NONOTIFY);

	retval = tty_alloc_file(filp);
	if (retval)
+16 −0
Original line number Diff line number Diff line
@@ -194,6 +194,11 @@ static int init_file(struct file *f, int flags, const struct cred *cred)
	 * refcount bumps we should reinitialize the reused file first.
	 */
	file_ref_init(&f->f_ref, 1);
	/*
	 * Disable permission and pre-content events for all files by default.
	 * They may be enabled later by file_set_fsnotify_mode_from_watchers().
	 */
	file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM);
	return 0;
}

@@ -375,7 +380,13 @@ struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
	if (IS_ERR(file)) {
		ihold(inode);
		path_put(&path);
		return file;
	}
	/*
	 * Disable all fsnotify events for pseudo files by default.
	 * They may be enabled by caller with file_set_fsnotify_mode().
	 */
	file_set_fsnotify_mode(file, FMODE_NONOTIFY);
	return file;
}
EXPORT_SYMBOL(alloc_file_pseudo);
@@ -400,6 +411,11 @@ struct file *alloc_file_pseudo_noaccount(struct inode *inode,
		return file;
	}
	file_init_path(file, &path, fops);
	/*
	 * Disable all fsnotify events for pseudo files by default.
	 * They may be enabled by caller with file_set_fsnotify_mode().
	 */
	file_set_fsnotify_mode(file, FMODE_NONOTIFY);
	return file;
}
EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount);
+12 −6
Original line number Diff line number Diff line
@@ -648,7 +648,7 @@ EXPORT_SYMBOL_GPL(fsnotify);
 * Later, fsnotify permission hooks do not check if there are permission event
 * watches, but that there were permission event watches at open time.
 */
void file_set_fsnotify_mode(struct file *file)
void file_set_fsnotify_mode_from_watchers(struct file *file)
{
	struct dentry *dentry = file->f_path.dentry, *parent;
	struct super_block *sb = dentry->d_sb;
@@ -665,7 +665,7 @@ void file_set_fsnotify_mode(struct file *file)
	 */
	if (likely(!fsnotify_sb_has_priority_watchers(sb,
						FSNOTIFY_PRIO_CONTENT))) {
		file->f_mode |= FMODE_NONOTIFY_PERM;
		file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
		return;
	}

@@ -676,7 +676,7 @@ void file_set_fsnotify_mode(struct file *file)
	if ((!d_is_dir(dentry) && !d_is_reg(dentry)) ||
	    likely(!fsnotify_sb_has_priority_watchers(sb,
						FSNOTIFY_PRIO_PRE_CONTENT))) {
		file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM;
		file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
		return;
	}

@@ -686,19 +686,25 @@ void file_set_fsnotify_mode(struct file *file)
	 */
	mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask);
	if (unlikely(fsnotify_object_watched(d_inode(dentry), mnt_mask,
				     FSNOTIFY_PRE_CONTENT_EVENTS)))
				     FSNOTIFY_PRE_CONTENT_EVENTS))) {
		/* Enable pre-content events */
		file_set_fsnotify_mode(file, 0);
		return;
	}

	/* Is parent watching for pre-content events on this file? */
	if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) {
		parent = dget_parent(dentry);
		p_mask = fsnotify_inode_watches_children(d_inode(parent));
		dput(parent);
		if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS)
		if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS) {
			/* Enable pre-content events */
			file_set_fsnotify_mode(file, 0);
			return;
		}
	}
	/* Nobody watching for pre-content events from this file */
	file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM;
	file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
}
#endif

+6 −5
Original line number Diff line number Diff line
@@ -905,7 +905,8 @@ static int do_dentry_open(struct file *f,
	f->f_sb_err = file_sample_sb_err(f);

	if (unlikely(f->f_flags & O_PATH)) {
		f->f_mode = FMODE_PATH | FMODE_OPENED | FMODE_NONOTIFY;
		f->f_mode = FMODE_PATH | FMODE_OPENED;
		file_set_fsnotify_mode(f, FMODE_NONOTIFY);
		f->f_op = &empty_fops;
		return 0;
	}
@@ -935,10 +936,10 @@ static int do_dentry_open(struct file *f,

	/*
	 * Set FMODE_NONOTIFY_* bits according to existing permission watches.
	 * If FMODE_NONOTIFY was already set for an fanotify fd, this doesn't
	 * change anything.
	 * If FMODE_NONOTIFY mode was already set for an fanotify fd or for a
	 * pseudo file, this call will not change the mode.
	 */
	file_set_fsnotify_mode(f);
	file_set_fsnotify_mode_from_watchers(f);
	error = fsnotify_open_perm(f);
	if (error)
		goto cleanup_all;
@@ -1122,7 +1123,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags,
	if (!IS_ERR(f)) {
		int error;

		f->f_mode |= FMODE_NONOTIFY;
		file_set_fsnotify_mode(f, FMODE_NONOTIFY);
		error = vfs_open(path, f);
		if (error) {
			fput(f);
+6 −0
Original line number Diff line number Diff line
@@ -960,6 +960,12 @@ int create_pipe_files(struct file **res, int flags)
	res[1] = f;
	stream_open(inode, res[0]);
	stream_open(inode, res[1]);
	/*
	 * Disable permission and pre-content events, but enable legacy
	 * inotify events for legacy users.
	 */
	file_set_fsnotify_mode(res[0], FMODE_NONOTIFY_PERM);
	file_set_fsnotify_mode(res[1], FMODE_NONOTIFY_PERM);
	return 0;
}

Loading