Module Name:    src
Committed By:   riastradh
Date:           Sun Mar 20 13:18:30 UTC 2022

Modified Files:
        src/sys/dev/usb: ualea.c

Log Message:
ualea(4): Enter the data under the softc lock.

This avoids a race with a concurrent ualea_get updating sc_needed,
which could lead to hang when requesting more entropy.

ualea(4) now survives

sysctl -w kern.entropy.depletion=1
cat </dev/random >/dev/null &
cat </dev/random >/dev/null &

without hanging for longer (even if yanked and reinserted in the
middle, although the detach path is not relevant to the bug this
change fixes).


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/usb/ualea.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/ualea.c
diff -u src/sys/dev/usb/ualea.c:1.18 src/sys/dev/usb/ualea.c:1.19
--- src/sys/dev/usb/ualea.c:1.18	Sun Mar 20 13:13:10 2022
+++ src/sys/dev/usb/ualea.c	Sun Mar 20 13:18:30 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ualea.c,v 1.18 2022/03/20 13:13:10 riastradh Exp $	*/
+/*	$NetBSD: ualea.c,v 1.19 2022/03/20 13:18:30 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ualea.c,v 1.18 2022/03/20 13:13:10 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ualea.c,v 1.19 2022/03/20 13:18:30 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -250,14 +250,18 @@ ualea_xfer_done(struct usbd_xfer *xfer, 
 	    "pktsize %"PRIu32" > %"PRIu16" (max)",
 	    pktsize, sc->sc_maxpktsize);
 
-	/* Add the data to the pool.  */
-	rnd_add_data(&sc->sc_rnd, pkt, pktsize, NBBY*pktsize);
-
 	/*
-	 * Debit what we contributed from what we need, mark the xfer
-	 * as done, and reschedule the xfer if we still need more.
+	 * Enter the data, debit what we contributed from what we need,
+	 * mark the xfer as done, and reschedule the xfer if we still
+	 * need more.
+	 *
+	 * Must enter the data under the lock so it happens atomically
+	 * with updating sc_needed -- otherwise we might hang needing
+	 * entropy and not scheduling xfer.  Must not touch pkt after
+	 * clearing sc_inflight and possibly rescheduling the xfer.
 	 */
 	mutex_enter(&sc->sc_lock);
+	rnd_add_data(&sc->sc_rnd, pkt, pktsize, NBBY*pktsize);
 	sc->sc_needed -= MIN(sc->sc_needed, pktsize);
 	sc->sc_inflight = false;
 	ualea_xfer(sc);

Reply via email to