⬢ DragonFlyBSD Kernel Audit
DF-5603 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/mmc/mmc_subr.c b/sys/bus/mmc/mmc_subr.c
index a41ce59..358a7c5 100644
--- a/sys/bus/mmc/mmc_subr.c
+++ b/sys/bus/mmc/mmc_subr.c
@@ -155,7 +155,14 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
 	struct mmc_command cmd;
 	int err;
 
-	KASSERT(timeout != 0, ("%s: no timeout", __func__));
+	/*
+	 * The timeout originates from card-controlled EXT_CSD data
+	 * (EXT_CSD[EXT_CSD_GEN_CMD6_TIME], see mmc.c) and must not be
+	 * trusted: a crafted or mis-programmed card reporting 0 must not
+	 * take an INVARIANTS kernel down at enumeration time.
+	 */
+	if (timeout == 0)
+		timeout = 500 * 1000;	/* 500 ms, as defaulted in mmc.c */
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SWITCH_FUNC;
@@ -184,7 +191,14 @@ mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout)
 	int err;
 	uint32_t status;
 
-	KASSERT(timeout != 0, ("%s: no timeout", __func__));
+	/*
+	 * The timeout originates from card-controlled EXT_CSD data
+	 * (EXT_CSD[EXT_CSD_GEN_CMD6_TIME], see mmc.c) and must not be
+	 * trusted: a crafted or mis-programmed card reporting 0 must not
+	 * take an INVARIANTS kernel down at enumeration time.
+	 */
+	if (timeout == 0)
+		timeout = 500 * 1000;	/* 500 ms, as defaulted in mmc.c */
 
 	/*
 	 * Note that when using a R1B response in mmc_switch(), bridges of
diff --git a/sys/bus/mmc/mmc.c b/sys/bus/mmc/mmc.c
index cf05140..d0dc879 100644
--- a/sys/bus/mmc/mmc.c
+++ b/sys/bus/mmc/mmc.c
@@ -1662,6 +1662,8 @@ mmc_discover_cards(struct mmc_softc *sc)
 			if (ivar->csd.spec_vers >= 6) {
 				ivar->cmd6_time = 10 *
 				    ivar->raw_ext_csd[EXT_CSD_GEN_CMD6_TIME];
+				if (ivar->cmd6_time == 0)
+					ivar->cmd6_time = 500 * 1000;
 			}
 			/* Find max supported bus width. */
 			ivar->bus_width = mmc_test_bus_width(sc);