Commit c4ef28fe authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull fsnotify updates from Jan Kara:
 "A couple of small fsnotify fixes and cleanups"

* tag 'fsnotify_for_v7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fanotify: replace deprecated strcpy in fanotify_info_copy_{name,name2}
  fsnotify: inotify: pass mark connector to fsnotify_recalc_mask()
  fanotify: call fanotify_events_supported() before path_permission() and security_path_notify()
  fanotify: avoid/silence premature LSM capability checks
  inotify: fix watch count leak when fsnotify_add_inode_mark_locked() fails
parents 04809172 0fdbe845
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#include <linux/fsnotify_backend.h>
#include <linux/path.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/exportfs.h>
#include <linux/hashtable.h>

@@ -218,7 +219,7 @@ static inline void fanotify_info_copy_name(struct fanotify_info *info,
		return;

	info->name_len = name->len;
	strcpy(fanotify_info_name(info), name->name);
	strscpy(fanotify_info_name(info), name->name, name->len + 1);
}

static inline void fanotify_info_copy_name2(struct fanotify_info *info,
@@ -228,7 +229,7 @@ static inline void fanotify_info_copy_name2(struct fanotify_info *info,
		return;

	info->name2_len = name->len;
	strcpy(fanotify_info_name2(info), name->name);
	strscpy(fanotify_info_name2(info), name->name, name->len + 1);
}

/*
+23 −27
Original line number Diff line number Diff line
@@ -1210,6 +1210,7 @@ static int fanotify_find_path(int dfd, const char __user *filename,

		*path = fd_file(f)->f_path;
		path_get(path);
		ret = 0;
	} else {
		unsigned int lookup_flags = 0;

@@ -1219,22 +1220,7 @@ static int fanotify_find_path(int dfd, const char __user *filename,
			lookup_flags |= LOOKUP_DIRECTORY;

		ret = user_path_at(dfd, filename, lookup_flags, path);
		if (ret)
			goto out;
	}

	/* you can only watch an inode if you have read permissions on it */
	ret = path_permission(path, MAY_READ);
	if (ret) {
		path_put(path);
		goto out;
	}

	ret = security_path_notify(path, mask, obj_type);
	if (ret)
		path_put(path);

out:
	return ret;
}

@@ -1615,17 +1601,18 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
	pr_debug("%s: flags=%x event_f_flags=%x\n",
		 __func__, flags, event_f_flags);

	if (!capable(CAP_SYS_ADMIN)) {
	/*
		 * An unprivileged user can setup an fanotify group with
		 * limited functionality - an unprivileged group is limited to
		 * notification events with file handles or mount ids and it
		 * cannot use unlimited queue/marks.
	 * An unprivileged user can setup an fanotify group with limited
	 * functionality - an unprivileged group is limited to notification
	 * events with file handles or mount ids and it cannot use unlimited
	 * queue/marks.
	 */
		if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) ||
		    !(flags & (FANOTIFY_FID_BITS | FAN_REPORT_MNT)))
	if (((flags & FANOTIFY_ADMIN_INIT_FLAGS) ||
	     !(flags & (FANOTIFY_FID_BITS | FAN_REPORT_MNT))) &&
	    !capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (!ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) {
		/*
		 * Setting the internal flag FANOTIFY_UNPRIV on the group
		 * prevents setting mount/filesystem marks on this group and
@@ -1990,8 +1977,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
	 * A user is allowed to setup sb/mount/mntns marks only if it is
	 * capable in the user ns where the group was created.
	 */
	if (!ns_capable(group->user_ns, CAP_SYS_ADMIN) &&
	    mark_type != FAN_MARK_INODE)
	if (mark_type != FAN_MARK_INODE &&
	    !ns_capable(group->user_ns, CAP_SYS_ADMIN))
		return -EPERM;

	/*
@@ -2057,6 +2044,15 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
			goto path_put_and_out;
	}

	/* you can only watch an inode if you have read permissions on it */
	ret = path_permission(&path, MAY_READ);
	if (ret)
		goto path_put_and_out;

	ret = security_path_notify(&path, mask, obj_type);
	if (ret)
		goto path_put_and_out;

	if (fid_mode) {
		ret = fanotify_test_fsid(path.dentry, flags, &__fsid);
		if (ret)
+2 −1
Original line number Diff line number Diff line
@@ -573,7 +573,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,

		/* update the inode with this new fsn_mark */
		if (dropped || do_inode)
			fsnotify_recalc_mask(inode->i_fsnotify_marks);
			fsnotify_recalc_mask(fsn_mark->connector);

	}

@@ -621,6 +621,7 @@ static int inotify_new_watch(struct fsnotify_group *group,
	if (ret) {
		/* we failed to get on the inode, get off the idr */
		inotify_remove_from_idr(group, tmp_i_mark);
		dec_inotify_watches(group->inotify_data.ucounts);
		goto out_err;
	}