Re: [PATCH] fanotify: report full event length for FIONREAD
From: Jan Kara
Date: Fri Jul 31 2026 - 08:30:48 EST
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 <chenyichong@xxxxxxxxxxxxx>
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 <jack@xxxxxxxx>
SUSE Labs, CR