summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-15 19:18:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-15 19:18:51 -0700
commitc4ef28fe97556db32ffcbfb4cf8bd7c2b34c3b9a (patch)
tree920f00305f51c4ae687c67a93f04933cbf09871d
parent048091722259b6e8d2ef3b138b0c121a2afabe61 (diff)
parent0fdbe845534f4e0b7243b7a44562c4486ce25fb4 (diff)
Merge tag 'fsnotify_for_v7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
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
-rw-r--r--fs/notify/fanotify/fanotify.h5
-rw-r--r--fs/notify/fanotify/fanotify_user.c50
-rw-r--r--fs/notify/inotify/inotify_user.c3
3 files changed, 28 insertions, 30 deletions
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 39e60218df7c..a0619e7694d5 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -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);
}
/*
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index c2dcb25151de..ae904451dfc0 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -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.
- */
- if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) ||
- !(flags & (FANOTIFY_FID_BITS | FAN_REPORT_MNT)))
- return -EPERM;
+ /*
+ * 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))) &&
+ !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)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 5e1845f2c25d..ed37491c1618 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -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;
}