DF-2803 / fix.diff
--- 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; |