mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
fanotify: fix false positive on permission events
commit7746e3bd4cupstream. 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:
committed by
Greg Kroah-Hartman
parent
d71240d260
commit
7baa02b0ae
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user