Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fanotify: fix false positive on permission events

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: abc77577a669 ("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>

authored by

Miklos Szeredi and committed by
Jan Kara
7746e3bd 1d51b370

+13 -8
+1 -1
fs/notify/fsnotify.c
··· 388 388 return hlist_entry_safe(node, struct fsnotify_mark, obj_list); 389 389 } 390 390 391 - static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) 391 + struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) 392 392 { 393 393 struct hlist_node *node = NULL; 394 394
+11 -7
fs/notify/mark.c
··· 457 457 */ 458 458 static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark) 459 459 { 460 - if (!mark) 461 - return true; 462 - 463 460 if (refcount_inc_not_zero(&mark->refcnt)) { 464 461 spin_lock(&mark->lock); 465 462 if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) { ··· 497 500 int type; 498 501 499 502 fsnotify_foreach_iter_type(type) { 503 + struct fsnotify_mark *mark = iter_info->marks[type]; 504 + 500 505 /* This can fail if mark is being removed */ 501 - if (!fsnotify_get_mark_safe(iter_info->marks[type])) { 502 - __release(&fsnotify_mark_srcu); 503 - goto fail; 506 + while (mark && !fsnotify_get_mark_safe(mark)) { 507 + if (mark->group == iter_info->current_group) { 508 + __release(&fsnotify_mark_srcu); 509 + goto fail; 510 + } 511 + /* This is a mark in an unrelated group, skip */ 512 + mark = fsnotify_next_mark(mark); 513 + iter_info->marks[type] = mark; 504 514 } 505 515 } 506 516 507 517 /* 508 - * Now that both marks are pinned by refcount in the inode / vfsmount 518 + * Now that all marks are pinned by refcount in the inode / vfsmount / etc 509 519 * lists, we can drop SRCU lock, and safely resume the list iteration 510 520 * once userspace returns. 511 521 */
+1
include/linux/fsnotify_backend.h
··· 915 915 unsigned int obj_type); 916 916 extern void fsnotify_get_mark(struct fsnotify_mark *mark); 917 917 extern void fsnotify_put_mark(struct fsnotify_mark *mark); 918 + struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark); 918 919 extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); 919 920 extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); 920 921