⬢ DragonFlyBSD Kernel Audit
DF-5120 / fix.diff
← back to finding ↓ download raw
--- virtio_random.c.orig
+++ virtio_random.c
@@ -193,7 +193,7 @@ static void
 vtrnd_harvest(struct vtrnd_softc *sc)
 {
 	struct sglist_seg segs[1];
 	struct sglist sg;
 	struct virtqueue *vq;
 	uint32_t value;
-	int error;
+	int error, i;
 
 	vq = sc->vtrnd_vq;
 
@@ -209,9 +209,24 @@ vtrnd_harvest(struct vtrnd_softc *sc)
 	/*
 	 * Poll for the response, but the command is likely already
 	 * done when we return from the notify.
+	 *
+	 * Bound the wait: virtqueue_poll() never returns while the host
+	 * has not advanced the used ring, and this runs from the periodic
+	 * softclock callout.  A wedged host entropy backend must degrade
+	 * to "no virtio entropy", not hang softclock forever.
 	 */
 	virtqueue_notify(vq, NULL);
-	virtqueue_poll(vq, NULL);
+	for (i = 0; i < 1000 && !virtqueue_pending(vq); i++)
+		DELAY(10);
+	if (!virtqueue_pending(vq)) {
+		/*
+		 * Device did not complete within ~10ms.  Leave the
+		 * descriptor queued; the virtqueue_empty() check above
+		 * then keeps disabling future harvests until reattach.
+		 */
+		return;
+	}
+	virtqueue_poll(vq, NULL);
 
 	add_buffer_randomness_src((const char *)&value, sizeof(value),
 	    RAND_SRC_VIRTIO);