⬢ DragonFlyBSD Kernel Audit
DF-4536 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/misc/lpt/lpt.c
+++ b/sys/dev/misc/lpt/lpt.c
@@ -109,6 +109,7 @@
 #define	LPTFLAGS(s)	((s)&0xfc)
 
 struct lpt_data {
+	struct spinlock sc_openlk;	/* serializes open/close transitions */
 	short	sc_state;
 	/* default case: negative prime, negative ack, handshake strobe,
 	   prime once */
@@ -365,6 +366,7 @@
 	uintptr_t irq;
 
 	sc->sc_primed = 0;	/* not primed yet */
+	spin_init(&sc->sc_openlk);
 	callout_init(&sc->sc_callout);
 
 	if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) {
@@ -455,11 +457,14 @@
 	if (!sc)
 		return (ENXIO);
 
+	spin_lock(&sc->sc_openlk);
 	if (sc->sc_state) {
+		spin_unlock(&sc->sc_openlk);
 		lprintf((LPT_NAME ": still open %x\n", sc->sc_state));
 		return(EBUSY);
-	} else
-		sc->sc_state |= LPTINIT;
+	}
+	sc->sc_state |= LPTINIT;
+	spin_unlock(&sc->sc_openlk);
 
 	sc->sc_flags = LPTFLAGS(minor(dev));
 
@@ -595,8 +600,12 @@
 	}
 	callout_stop(&sc->sc_callout);
 	ppb_wctr(ppbus, LPC_NINIT);
+	spin_lock(&sc->sc_openlk);
 	kfree(sc->sc_inbuf, M_LPT);
+	sc->sc_inbuf = NULL;
 	kfree(sc->sc_statbuf, M_LPT);
+	sc->sc_statbuf = NULL;
+	spin_unlock(&sc->sc_openlk);
 
 end_close:
 	/* release the bus anyway