Skip to content

Commit 4ed6814

Browse files
amir73iljankara
authored andcommitted
fanotify: prepare for implicit event flags in mark mask
So far, all flags that can be set in an fanotify mark mask can be set explicitly by a call to fanotify_mark(2). Prepare for defining implicit event flags that cannot be set by user with fanotify_mark(2), similar to how inotify/dnotify implicitly set the FS_EVENT_ON_CHILD flag. Implicit event flags cannot be removed by user and mark gets destroyed when only implicit event flags remain in the mask. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 3ef8665 commit 4ed6814

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

fs/notify/fanotify/fanotify_user.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -656,28 +656,35 @@ static int fanotify_find_path(int dfd, const char __user *filename,
656656
}
657657

658658
static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
659-
__u32 mask,
660-
unsigned int flags,
661-
int *destroy)
659+
__u32 mask, unsigned int flags,
660+
__u32 umask, int *destroy)
662661
{
663662
__u32 oldmask = 0;
664663

664+
/* umask bits cannot be removed by user */
665+
mask &= ~umask;
665666
spin_lock(&fsn_mark->lock);
666667
if (!(flags & FAN_MARK_IGNORED_MASK)) {
667668
oldmask = fsn_mark->mask;
668669
fsn_mark->mask &= ~mask;
669670
} else {
670671
fsn_mark->ignored_mask &= ~mask;
671672
}
672-
*destroy = !(fsn_mark->mask | fsn_mark->ignored_mask);
673+
/*
674+
* We need to keep the mark around even if remaining mask cannot
675+
* result in any events (e.g. mask == FAN_ONDIR) to support incremenal
676+
* changes to the mask.
677+
* Destroy mark when only umask bits remain.
678+
*/
679+
*destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);
673680
spin_unlock(&fsn_mark->lock);
674681

675682
return mask & oldmask;
676683
}
677684

678685
static int fanotify_remove_mark(struct fsnotify_group *group,
679686
fsnotify_connp_t *connp, __u32 mask,
680-
unsigned int flags)
687+
unsigned int flags, __u32 umask)
681688
{
682689
struct fsnotify_mark *fsn_mark = NULL;
683690
__u32 removed;
@@ -691,7 +698,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
691698
}
692699

693700
removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
694-
&destroy_mark);
701+
umask, &destroy_mark);
695702
if (removed & fsnotify_conn_mask(fsn_mark->connector))
696703
fsnotify_recalc_mask(fsn_mark->connector);
697704
if (destroy_mark)
@@ -707,25 +714,26 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
707714

708715
static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
709716
struct vfsmount *mnt, __u32 mask,
710-
unsigned int flags)
717+
unsigned int flags, __u32 umask)
711718
{
712719
return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
713-
mask, flags);
720+
mask, flags, umask);
714721
}
715722

716723
static int fanotify_remove_sb_mark(struct fsnotify_group *group,
717-
struct super_block *sb, __u32 mask,
718-
unsigned int flags)
724+
struct super_block *sb, __u32 mask,
725+
unsigned int flags, __u32 umask)
719726
{
720-
return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, flags);
727+
return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
728+
flags, umask);
721729
}
722730

723731
static int fanotify_remove_inode_mark(struct fsnotify_group *group,
724732
struct inode *inode, __u32 mask,
725-
unsigned int flags)
733+
unsigned int flags, __u32 umask)
726734
{
727735
return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
728-
flags);
736+
flags, umask);
729737
}
730738

731739
static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
@@ -1175,13 +1183,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
11751183
case FAN_MARK_REMOVE:
11761184
if (mark_type == FAN_MARK_MOUNT)
11771185
ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
1178-
flags);
1186+
flags, 0);
11791187
else if (mark_type == FAN_MARK_FILESYSTEM)
11801188
ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
1181-
flags);
1189+
flags, 0);
11821190
else
11831191
ret = fanotify_remove_inode_mark(group, inode, mask,
1184-
flags);
1192+
flags, 0);
11851193
break;
11861194
default:
11871195
ret = -EINVAL;

0 commit comments

Comments
 (0)