fanotify: fix false positive on permission events

commit 7746e3bd4c upstream.

fsnotify_get_mark_safe() may return false for a mark on an unrelated group,
which results in bypassing the permission check.

Fix by skipping over detached marks that are not in the current group.

CC: stable@vger.kernel.org
Fixes: abc77577a6 ("fsnotify: Provide framework for dropping SRCU lock in ->handle_event")
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Link: https://patch.msgid.link/20260410144950.156160-1-mszeredi@redhat.com
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Miklos Szeredi
2026-05-14 15:30:15 +02:00
committed by Greg Kroah-Hartman
parent d71240d260
commit 7baa02b0ae
3 changed files with 13 additions and 8 deletions
+1 -1
View File
@@ -444,7 +444,7 @@ static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector
return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
}
static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
{
struct hlist_node *node = NULL;
+11 -7
View File
@@ -453,9 +453,6 @@ EXPORT_SYMBOL_GPL(fsnotify_put_mark);
*/
static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark)
{
if (!mark)
return true;
if (refcount_inc_not_zero(&mark->refcnt)) {
spin_lock(&mark->lock);
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) {
@@ -496,15 +493,22 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
int type;
fsnotify_foreach_iter_type(type) {
struct fsnotify_mark *mark = iter_info->marks[type];
/* This can fail if mark is being removed */
if (!fsnotify_get_mark_safe(iter_info->marks[type])) {
__release(&fsnotify_mark_srcu);
goto fail;
while (mark && !fsnotify_get_mark_safe(mark)) {
if (mark->group == iter_info->current_group) {
__release(&fsnotify_mark_srcu);
goto fail;
}
/* This is a mark in an unrelated group, skip */
mark = fsnotify_next_mark(mark);
iter_info->marks[type] = mark;
}
}
/*
* Now that both marks are pinned by refcount in the inode / vfsmount
* Now that all marks are pinned by refcount in the inode / vfsmount / etc
* lists, we can drop SRCU lock, and safely resume the list iteration
* once userspace returns.
*/
+1
View File
@@ -912,6 +912,7 @@ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
unsigned int obj_type);
extern void fsnotify_get_mark(struct fsnotify_mark *mark);
extern void fsnotify_put_mark(struct fsnotify_mark *mark);
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark);
extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);