Commit 635bc4de authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara
Browse files

fsnotify: do not generate ACCESS/MODIFY events on child for special files

inotify/fanotify do not allow users with no read access to a file to
subscribe to events (e.g. IN_ACCESS/IN_MODIFY), but they do allow the
same user to subscribe for watching events on children when the user
has access to the parent directory (e.g. /dev).

Users with no read access to a file but with read access to its parent
directory can still stat the file and see if it was accessed/modified
via atime/mtime change.

The same is not true for special files (e.g. /dev/null). Users will not
generally observe atime/mtime changes when other users read/write to
special files, only when someone sets atime/mtime via utimensat().

Align fsnotify events with this stat behavior and do not generate
ACCESS/MODIFY events to parent watchers on read/write of special files.
The events are still generated to parent watchers on utimensat(). This
closes some side-channels that could be possibly used for information
exfiltration [1].

[1] https://snee.la/pdf/pubs/file-notification-attacks.pdf



Reported-by: default avatarSudheendra Raghav Neela <sneela@tugraz.at>
CC: stable@vger.kernel.org
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 7d0a66e4
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -270,8 +270,15 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
	/*
	 * Include parent/name in notification either if some notification
	 * groups require parent info or the parent is interested in this event.
	 * The parent interest in ACCESS/MODIFY events does not apply to special
	 * files, where read/write are not on the filesystem of the parent and
	 * events can provide an undesirable side-channel for information
	 * exfiltration.
	 */
	parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
	parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS &&
			    !(data_type == FSNOTIFY_EVENT_PATH &&
			      d_is_special(dentry) &&
			      (mask & (FS_ACCESS | FS_MODIFY)));
	if (parent_needed || parent_interested) {
		/* When notifying parent, child should be passed as data */
		WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));