Re: [PATCH] fanotify: report full event length for FIONREAD

Jan Kara <[email protected]> Fri, 31 Jul 2026 14:19:22 +0200
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <gpxknoebwrtfxspbgi7jhtprzimno2hdzb6pee2iwwtsatranb@prvukrmdldfp>
On Fri 31-07-26 10:18:27, Yichong Chen wrote:
> fanotify_ioctl(FIONREAD) reports the number of bytes available to read
> from the event queue.  It currently accounts only FAN_EVENT_METADATA_LEN
> for each queued event.
> 
> That underestimates events that carry additional information records, such
> as FAN_REPORT_DFID_NAME events.  A userspace program that uses FIONREAD to
> size its read buffer can receive a length that is smaller than the next
> event.  Reading with that buffer then fails with -EINVAL, while a larger
> buffer succeeds and reports a larger metadata.event_len.
> 
> Use fanotify_event_len() when summing queued events so FIONREAD includes
> all info records.
> 
> Fixes: 5e469c830fdb ("fanotify: copy event fid info to user")
> Signed-off-by: Yichong Chen <[email protected]>

Thanks! I've added the patch to my tree.

								Honza

> ---
>  fs/notify/fanotify/fanotify_user.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
> index 9ee373ff5840..33693886b7d8 100644
> --- a/fs/notify/fanotify/fanotify_user.c
> +++ b/fs/notify/fanotify/fanotify_user.c
> @@ -1150,11 +1150,13 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>  {
>  	struct fsnotify_group *group;
>  	struct fsnotify_event *fsn_event;
> +	unsigned int info_mode;
>  	void __user *p;
>  	int ret = -ENOTTY;
>  	size_t send_len = 0;
>  
>  	group = file->private_data;
> +	info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
>  
>  	p = (void __user *) arg;
>  
> @@ -1162,7 +1164,8 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>  	case FIONREAD:
>  		spin_lock(&group->notification_lock);
>  		list_for_each_entry(fsn_event, &group->notification_list, list)
> -			send_len += FAN_EVENT_METADATA_LEN;
> +			send_len += fanotify_event_len(info_mode,
> +						       FANOTIFY_E(fsn_event));
>  		spin_unlock(&group->notification_lock);
>  		ret = put_user(send_len, (int __user *) p);
>  		break;
> -- 
> 2.51.0
> 
-- 
Jan Kara <[email protected]>
SUSE Labs, CR