From: Karel Zak Date: Mon, 15 Jun 2026 11:15:01 +0000 (+0200) Subject: libmount: detect fanotify queue overflow in monitor X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a9ce458c65aacdf1676987f6fc15371643907976;p=thirdparty%2Futil-linux.git libmount: detect fanotify queue overflow in monitor When the fanotify event queue overflows under sustained mount churn, the kernel sends a FAN_Q_OVERFLOW event. The fanotify_next_fs() function did not check for this, causing it to access invalid memory (the overflow event carries no fanotify_event_info_mnt payload) and silently drop the overflow notification. The consumer never learned that events were lost, so its mount-unit view could permanently diverge from the kernel. Detect FAN_Q_OVERFLOW, discard the remaining buffered events (they are unreliable after an overflow), and return -EOVERFLOW so the caller can perform a full rescan. Signed-off-by: Karel Zak --- diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c index e99607a3c..fd0aa628a 100644 --- a/libmount/src/monitor.c +++ b/libmount/src/monitor.c @@ -482,19 +482,27 @@ int mnt_monitor_event_cleanup(struct libmnt_monitor *mn) * (as returned by mnt_monitor_next_change()). If the event does not provide * details, it returns -ENOTSUP. * + * If the fanotify event queue has overflowed (events were lost due to + * sustained mount churn), this function returns -EOVERFLOW. In this case, + * the remaining buffered events are discarded and the caller should + * perform a full rescan to recover a consistent mount state. + * * * * while (mnt_monitor_next_change(mn, NULL, &type) == 0) { * if (type == MNT_MONITOR_TYPE_FANOTIFY) { - * while (mnt_monitor_event_next_fs(mn, fs) == 0) { + * int rc; + * while ((rc = mnt_monitor_event_next_fs(mn, fs)) == 0) { * printf("ID=%ju\n", mnt_fs_get_uniq_id(fs)); * } + * if (rc == -EOVERFLOW) + * full_rescan(); * } * } * * * - * Returns: 0 on success, 1 no more data, <0 on error + * Returns: 0 on success, 1 no more data, -EOVERFLOW on queue overflow, <0 on error * * Since: 2.42 */ diff --git a/libmount/src/monitor_fanotify.c b/libmount/src/monitor_fanotify.c index 20d20ff3a..6d3b4617a 100644 --- a/libmount/src/monitor_fanotify.c +++ b/libmount/src/monitor_fanotify.c @@ -197,6 +197,12 @@ static int fanotify_next_fs(struct libmnt_monitor *mn, struct monitor_entry *me, meta->vers != FANOTIFY_METADATA_VERSION) goto nothing; + if (meta->mask & FAN_Q_OVERFLOW) { + DBG_OBJ(MONITOR, mn, ul_debug("fanotify queue overflow")); + data->remaining = 0; + return -EOVERFLOW; + } + thislen = meta->event_len - sizeof(*meta); mnt = (struct fanotify_event_info_mnt *)