DragonFlyBSD Kernel Audit
DF-2803 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/kern_udev.c
+++ b/sys/kern/kern_udev.c
@@ -123,6 +123,10 @@ static TAILQ_HEAD(, udev_softc) udevq;
 static TAILQ_HEAD(, udev_event_kernel) udev_evq;
 static struct kqinfo udev_kq;
 static struct lock udev_lk;
+
+/* Hard cap on queued-but-undelivered events; drop beyond this. */
+#define UDEV_EVQ_MAX	8192
+
 static int udev_evqlen;
 static int udev_initiated_count;
 static int udev_open_count;
@@ -503,19 +507,29 @@ static void
 udev_event_insert(int ev_type, prop_dictionary_t dict)
 {
 	struct udev_event_kernel *ev;
 	prop_dictionary_t dict_copy;
 
 	/* Only start queing events after client has initiated properly */
 	if (udev_initiated_count) {
+		/*
+		 * Bound the queue: a slow or stalled initiated reader must
+		 * not turn device activity into unbounded kernel memory.
+		 * Check under udev_lk (udev_evqlen is only meaningful
+		 * under the lock) and drop the event when full.
+		 */
+		lockmgr(&udev_lk, LK_EXCLUSIVE);
+		if (udev_evqlen >= UDEV_EVQ_MAX) {
+			++udev_seq;
+			if (udev_seqwait)
+				wakeup(&udev_seqwait);
+			lockmgr(&udev_lk, LK_RELEASE);
+			return;
+		}
 		dict_copy = prop_dictionary_copy(dict);
-		if (dict_copy == NULL)
+		if (dict_copy == NULL) {
+			lockmgr(&udev_lk, LK_RELEASE);
 			return;
+		}
 		ev = objcache_get(udev_event_kernel_cache, M_WAITOK);
 		ev->ev.ev_dict = dict_copy;
 		ev->ev.ev_type = ev_type;
 
-		lockmgr(&udev_lk, LK_EXCLUSIVE);
 		TAILQ_INSERT_TAIL(&udev_evq, ev, link);
 		++udev_evqlen;
 		++udev_seq;