]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: detect fanotify queue overflow in monitor
authorKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2026 11:15:01 +0000 (13:15 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2026 11:15:01 +0000 (13:15 +0200)
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 <kzak@redhat.com>
libmount/src/monitor.c
libmount/src/monitor_fanotify.c

index e99607a3c9ccb7394c22825422a29dddb5782ff3..fd0aa628a8293d9cb770c23f1556346eb834bd26 100644 (file)
@@ -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.
+ *
  * <informalexample>
  *  <programlisting>
  *   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();
  *     }
  *   }
  *  </programlisting>
  * </informalexample>
  *
- * 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
  */
index 20d20ff3aa5607b7952e9f441825a15b314a091a..6d3b4617ac19d4a5d74a61fd38fc70e448449e72 100644 (file)
@@ -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 *)