⬢ DragonFlyBSD Kernel Audit
DF-4893 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/ath/ath_hal/ah_osdep.c
+++ b/sys/dev/netif/ath/ath_hal/ah_osdep.c
@@ -185,184 +185,20 @@
 #undef	HAL_DEBUG_UNMASKABLE
 #endif /* AH_DEBUG */
 
-#ifdef AH_DEBUG_ALQ
-/*
- * ALQ register tracing support.
- *
- * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
- * writes to the file /tmp/ath_hal.log.  The file format is a simple
- * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
- * and then decode the file with the arcode program (that is part of the
- * HAL).  If you start+stop tracing the data will be appended to an
- * existing file.
+/* DF-4893: the AH_DEBUG_ALQ block (ALQ register tracing) was removed.
  *
- * NB: doesn't handle multiple devices properly; only one DEVICE record
- *     is emitted and the different devices are not identified.
- */
-/*#include <sys/alq.h> FreeBSD */
-/*#include <sys/pcpu.h> FreeBSD */
-#include <dev/netif/ath/ath_hal/ah_decode.h>
-
-static	struct alq *ath_hal_alq;
-static	int ath_hal_alq_emitdev;	/* need to emit DEVICE record */
-static	u_int ath_hal_alq_lost;		/* count of lost records */
-static	char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log";
-
-SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW,
-    &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile");
-
-static	u_int ath_hal_alq_qsize = 64*1024;
-
-static int
-ath_hal_setlogging(int enable)
-{
-	int error;
-
-	if (enable) {
-		error = alq_open(&ath_hal_alq, ath_hal_logfile,
-			curthread->td_ucred, ALQ_DEFAULT_CMODE,
-			sizeof (struct athregrec), ath_hal_alq_qsize);
-		ath_hal_alq_lost = 0;
-		ath_hal_alq_emitdev = 1;
-		kprintf("ath_hal: logging to %s enabled\n",
-			ath_hal_logfile);
-	} else {
-		if (ath_hal_alq)
-			alq_close(ath_hal_alq);
-		ath_hal_alq = NULL;
-		kprintf("ath_hal: logging disabled\n");
-		error = 0;
-	}
-	return (error);
-}
-
-static int
-sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
-{
-	int error, enable;
-
-	enable = (ath_hal_alq != NULL);
-        error = sysctl_handle_int(oidp, &enable, 0, req);
-        if (error || !req->newptr)
-                return (error);
-	else
-		return (ath_hal_setlogging(enable));
-}
-SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
-	0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
-SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
-	&ath_hal_alq_qsize, 0, "In-memory log size (#records)");
-SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
-	&ath_hal_alq_lost, 0, "Register operations not logged");
-
-static struct ale *
-ath_hal_alq_get(struct ath_hal *ah)
-{
-	struct ale *ale;
-
-	if (ath_hal_alq_emitdev) {
-		ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
-		if (ale) {
-			struct athregrec *r =
-				(struct athregrec *) ale->ae_data;
-			r->op = OP_DEVICE;
-			r->reg = 0;
-			r->val = ah->ah_devid;
-			alq_post(ath_hal_alq, ale);
-			ath_hal_alq_emitdev = 0;
-		} else
-			ath_hal_alq_lost++;
-	}
-	ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
-	if (!ale)
-		ath_hal_alq_lost++;
-	return ale;
-}
-
-void
-ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
-{
-	bus_space_tag_t tag = BUSTAG(ah);
-	bus_space_handle_t h = ah->ah_sh;
-
-#ifdef	AH_DEBUG
-	/* Debug - complain if we haven't fully waken things up */
-	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
-	    ah->ah_powerMode != HAL_PM_AWAKE) {
-		ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
-		    __func__, reg, val, ah->ah_powerMode);
-	}
-#endif
-
-	if (ath_hal_alq) {
-		struct ale *ale = ath_hal_alq_get(ah);
-		if (ale) {
-			struct athregrec *r = (struct athregrec *) ale->ae_data;
-			r->threadid = curthread->td_tid;
-			r->op = OP_WRITE;
-			r->reg = reg;
-			r->val = val;
-			alq_post(ath_hal_alq, ale);
-		}
-	}
-	if (ah->ah_config.ah_serialise_reg_war)
-		lockmgr(&ah_regser_mtx, LK_EXCLUSIVE);
-	bus_space_write_4(tag, h, reg, val);
-	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
-	if (ah->ah_config.ah_serialise_reg_war)
-		lockmgr(&ah_regser_mtx, LK_RELEASE);
-}
-
-u_int32_t
-ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
-{
-	bus_space_tag_t tag = BUSTAG(ah);
-	bus_space_handle_t h = ah->ah_sh;
-	u_int32_t val;
-
-	/* Debug - complain if we haven't fully waken things up */
-	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
-	    ah->ah_powerMode != HAL_PM_AWAKE) {
-		ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
-		    __func__, reg, ah->ah_powerMode);
-	}
-
-	if (ah->ah_config.ah_serialise_reg_war)
-		lockmgr(&ah_regser_mtx, LK_EXCLUSIVE);
-	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
-	val = bus_space_read_4(tag, h, reg);
-	if (ah->ah_config.ah_serialise_reg_war)
-		lockmgr(&ah_regser_mtx, LK_RELEASE);
-	if (ath_hal_alq) {
-		struct ale *ale = ath_hal_alq_get(ah);
-		if (ale) {
-			struct athregrec *r = (struct athregrec *) ale->ae_data;
-			r->threadid = curthread->td_tid;
-			r->op = OP_READ;
-			r->reg = reg;
-			r->val = val;
-			alq_post(ath_hal_alq, ale);
-		}
-	}
-	return val;
-}
-
-void
-OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
-{
-	if (ath_hal_alq) {
-		struct ale *ale = ath_hal_alq_get(ah);
-		if (ale) {
-			struct athregrec *r = (struct athregrec *) ale->ae_data;
-			r->threadid = curthread->td_tid;
-			r->op = OP_MARK;
-			r->reg = id;
-			r->val = v;
-			alq_post(ath_hal_alq, ale);
-		}
-	}
-}
-#else /* AH_DEBUG_ALQ */
+ * It was inherited FreeBSD glue that can never compile on DragonFly:
+ *  - the AH_DEBUG_ALQ option mapping is commented out (sys/conf/options);
+ *  - no alq(9) implementation or <sys/alq.h> exists in this tree
+ *    (the include was commented out here);
+ *  - its ath_hal_reg_read() called ath_hal_reg_whilst_asleep(), which is
+ *    only defined under AH_DEBUG.
+ * The block also carried a TOCTOU: consumers checked the unlocked global
+ * `ath_hal_alq` (NULL test) and then passed it to alq_get()/alq_post()
+ * while the sysctl disable path ran alq_close() + NULL-store on it -- a
+ * use-after-free if the block is ever revived without locking.  If alq(9)
+ * is imported later, re-add the block with the global protected by a mutex
+ * on BOTH the consumer and the sysctl closer paths. */
 
 /*
  * Memory-mapped device register read/write.  These are here
@@ -422,7 +258,6 @@
 		lockmgr(&ah_regser_mtx, LK_RELEASE);
 	return val;
 }
-#endif /* AH_DEBUG_ALQ */
 
 #ifdef AH_ASSERT
 void