Skip to content

Commit 895ebbe

Browse files
Miklos Szeredigregkh
authored andcommitted
fanotify: fix false positive on permission events
commit 7746e3b 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: abc7757 ("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>
1 parent f39501e commit 895ebbe

3 files changed

Lines changed: 13 additions & 8 deletions

File tree

fs/notify/fsnotify.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector
398398
return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
399399
}
400400

401-
static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
401+
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
402402
{
403403
struct hlist_node *node = NULL;
404404

fs/notify/mark.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,6 @@ EXPORT_SYMBOL_GPL(fsnotify_put_mark);
380380
*/
381381
static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark)
382382
{
383-
if (!mark)
384-
return true;
385-
386383
if (refcount_inc_not_zero(&mark->refcnt)) {
387384
spin_lock(&mark->lock);
388385
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) {
@@ -423,15 +420,22 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
423420
int type;
424421

425422
fsnotify_foreach_iter_type(type) {
423+
struct fsnotify_mark *mark = iter_info->marks[type];
424+
426425
/* This can fail if mark is being removed */
427-
if (!fsnotify_get_mark_safe(iter_info->marks[type])) {
428-
__release(&fsnotify_mark_srcu);
429-
goto fail;
426+
while (mark && !fsnotify_get_mark_safe(mark)) {
427+
if (mark->group == iter_info->current_group) {
428+
__release(&fsnotify_mark_srcu);
429+
goto fail;
430+
}
431+
/* This is a mark in an unrelated group, skip */
432+
mark = fsnotify_next_mark(mark);
433+
iter_info->marks[type] = mark;
430434
}
431435
}
432436

433437
/*
434-
* Now that both marks are pinned by refcount in the inode / vfsmount
438+
* Now that all marks are pinned by refcount in the inode / vfsmount / etc
435439
* lists, we can drop SRCU lock, and safely resume the list iteration
436440
* once userspace returns.
437441
*/

include/linux/fsnotify_backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group
817817
}
818818
extern void fsnotify_get_mark(struct fsnotify_mark *mark);
819819
extern void fsnotify_put_mark(struct fsnotify_mark *mark);
820+
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark);
820821
extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
821822
extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);
822823

0 commit comments

Comments
 (0)