Commit 36c79551 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fsnotify_for_v5.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify fixes from Jan Kara:
 "A fix for permission checking with fanotify unpriviledged groups.

  Also there's a small update in MAINTAINERS file for fanotify"

* tag 'fsnotify_for_v5.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fanotify: fix permission model of unprivileged group
  MAINTAINERS: Add Matthew Bobrowski as a reviewer
parents 8124c8a6 a8b98c80
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6945,6 +6945,7 @@ F: net/core/failover.c
FANOTIFY
M:	Jan Kara <jack@suse.cz>
R:	Amir Goldstein <amir73il@gmail.com>
R:	Matthew Bobrowski <repnop@google.com>
L:	linux-fsdevel@vger.kernel.org
S:	Maintained
F:	fs/notify/fanotify/
+24 −6
Original line number Diff line number Diff line
@@ -424,11 +424,18 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
	 * events generated by the listener process itself, without disclosing
	 * the pids of other processes.
	 */
	if (!capable(CAP_SYS_ADMIN) &&
	if (FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
	    task_tgid(current) != event->pid)
		metadata.pid = 0;

	if (path && path->mnt && path->dentry) {
	/*
	 * For now, fid mode is required for an unprivileged listener and
	 * fid mode does not report fd in events.  Keep this check anyway
	 * for safety in case fid mode requirement is relaxed in the future
	 * to allow unprivileged listener to get events with no fd and no fid.
	 */
	if (!FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
	    path && path->mnt && path->dentry) {
		fd = create_fd(group, path, &f);
		if (fd < 0)
			return fd;
@@ -1040,6 +1047,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
	int f_flags, fd;
	unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
	unsigned int class = flags & FANOTIFY_CLASS_BITS;
	unsigned int internal_flags = 0;

	pr_debug("%s: flags=%x event_f_flags=%x\n",
		 __func__, flags, event_f_flags);
@@ -1053,6 +1061,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
		 */
		if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode)
			return -EPERM;

		/*
		 * Setting the internal flag FANOTIFY_UNPRIV on the group
		 * prevents setting mount/filesystem marks on this group and
		 * prevents reporting pid and open fd in events.
		 */
		internal_flags |= FANOTIFY_UNPRIV;
	}

#ifdef CONFIG_AUDITSYSCALL
@@ -1105,7 +1120,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
		goto out_destroy_group;
	}

	group->fanotify_data.flags = flags;
	group->fanotify_data.flags = flags | internal_flags;
	group->memcg = get_mem_cgroup_from_mm(current->mm);

	group->fanotify_data.merge_hash = fanotify_alloc_merge_hash();
@@ -1305,11 +1320,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
	group = f.file->private_data;

	/*
	 * An unprivileged user is not allowed to watch a mount point nor
	 * a filesystem.
	 * An unprivileged user is not allowed to setup mount nor filesystem
	 * marks.  This also includes setting up such marks by a group that
	 * was initialized by an unprivileged user.
	 */
	ret = -EPERM;
	if (!capable(CAP_SYS_ADMIN) &&
	if ((!capable(CAP_SYS_ADMIN) ||
	     FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
	    mark_type != FAN_MARK_INODE)
		goto fput_and_out;

@@ -1460,6 +1477,7 @@ static int __init fanotify_user_setup(void)
	max_marks = clamp(max_marks, FANOTIFY_OLD_DEFAULT_MAX_MARKS,
				     FANOTIFY_DEFAULT_MAX_USER_MARKS);

	BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10);
	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);

+1 −1
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f)
	struct fsnotify_group *group = f->private_data;

	seq_printf(m, "fanotify flags:%x event-flags:%x\n",
		   group->fanotify_data.flags,
		   group->fanotify_data.flags & FANOTIFY_INIT_FLAGS,
		   group->fanotify_data.f_flags);

	show_fdinfo(m, f, fanotify_fdinfo);
+4 −0
Original line number Diff line number Diff line
@@ -51,6 +51,10 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */
#define FANOTIFY_INIT_FLAGS	(FANOTIFY_ADMIN_INIT_FLAGS | \
				 FANOTIFY_USER_INIT_FLAGS)

/* Internal group flags */
#define FANOTIFY_UNPRIV		0x80000000
#define FANOTIFY_INTERNAL_GROUP_FLAGS	(FANOTIFY_UNPRIV)

#define FANOTIFY_MARK_TYPE_BITS	(FAN_MARK_INODE | FAN_MARK_MOUNT | \
				 FAN_MARK_FILESYSTEM)