Skip to content

Commit 7372e79

Browse files
amir73iljankara
authored andcommitted
fanotify: fix logic of reporting name info with watched parent
The victim inode's parent and name info is required when an event needs to be delivered to a group interested in filename info OR when the inode's parent is interested in an event on its children. Let us call the first condition 'parent_needed' and the second condition 'parent_interested'. In fsnotify_parent(), the condition where the inode's parent is interested in some events on its children, but not necessarily interested the specific event is called 'parent_watched'. fsnotify_parent() tests the condition (!parent_watched && !parent_needed) for sending the event without parent and name info, which is correct. It then wrongly assumes that parent_watched implies !parent_needed and tests the condition (parent_watched && !parent_interested) for sending the event without parent and name info, which is wrong, because parent may still be needed by some group. For example, after initializing a group with FAN_REPORT_DFID_NAME and adding a FAN_MARK_MOUNT with FAN_OPEN mask, open events on non-directory children of "testdir" are delivered with file name info. After adding another mark to the same group on the parent "testdir" with FAN_CLOSE|FAN_EVENT_ON_CHILD mask, open events on non-directory children of "testdir" are no longer delivered with file name info. Fix the logic and use auxiliary variables to clarify the conditions. Fixes: 9b93f33 ("fsnotify: send event with parent/name info to sb/mount/non-dir marks") Cc: [email protected]#v5.9 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent b7cbaf5 commit 7372e79

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

fs/notify/fsnotify.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
178178
struct inode *inode = d_inode(dentry);
179179
struct dentry *parent;
180180
bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
181+
bool parent_needed, parent_interested;
181182
__u32 p_mask;
182183
struct inode *p_inode = NULL;
183184
struct name_snapshot name;
@@ -193,7 +194,8 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
193194
return 0;
194195

195196
parent = NULL;
196-
if (!parent_watched && !fsnotify_event_needs_parent(inode, mnt, mask))
197+
parent_needed = fsnotify_event_needs_parent(inode, mnt, mask);
198+
if (!parent_watched && !parent_needed)
197199
goto notify;
198200

199201
/* Does parent inode care about events on children? */
@@ -205,17 +207,17 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
205207

206208
/*
207209
* Include parent/name in notification either if some notification
208-
* groups require parent info (!parent_watched case) or the parent is
209-
* interested in this event.
210+
* groups require parent info or the parent is interested in this event.
210211
*/
211-
if (!parent_watched || (mask & p_mask & ALL_FSNOTIFY_EVENTS)) {
212+
parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
213+
if (parent_needed || parent_interested) {
212214
/* When notifying parent, child should be passed as data */
213215
WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
214216

215217
/* Notify both parent and child with child name info */
216218
take_dentry_name_snapshot(&name, dentry);
217219
file_name = &name.name;
218-
if (parent_watched)
220+
if (parent_interested)
219221
mask |= FS_EVENT_ON_CHILD;
220222
}
221223

0 commit comments

Comments
 (0)