⬢ DragonFlyBSD Kernel Audit
DF-2807 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/kern_udev.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/kern/kern_udev.c	2026-10-26 01:39:50.408417911 +0000
@@ -568,8 +568,12 @@
 		return NULL;
 	}
 
-	prop_object_release(ev->ev.ev_dict);
-
+	/*
+	 * DF-2807 NOTE: do NOT release ev->ev.ev_dict here.  The event
+	 * must stay consumable when the caller turns out to have too
+	 * small a buffer (EMSGSIZE retry).  The reference is dropped at
+	 * the consume point (marker advance) in udev_dev_read instead.
+	 */
 	xml = prop_dictionary_externalize(dict);
 
 	prop_object_release(dict);
@@ -844,13 +852,26 @@
 					break;
 				}
 				len = strlen(xml) + 1; /* include terminator */
-				if (uio->uio_resid < len)
-					error = ENOMEM;
-				else
-					error = uiomove((caddr_t)xml, len, uio);
+				if (uio->uio_resid < len) {
+					/*
+					 * Short buffer: do NOT consume the
+					 * event.  The caller retries with a
+					 * larger buffer.
+					 */
+					kfree(xml, M_TEMP);
+					error = EMSGSIZE;
+					break;
+				}
+				error = uiomove((caddr_t)xml, len, uio);
 				kfree(xml, M_TEMP);
 
 				/*
+				 * Event consumed: drop the queue reference
+				 * formerly dropped inside externalize.
+				 */
+				prop_object_release(ev->ev.ev_dict);
+
+				/*
 				 * Move the marker
 				 */
 				TAILQ_REMOVE(&udev_evq, &softc->marker, link);