DragonFlyBSD Kernel Audit
DF-1989 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/crypto/tpm/tpm_crb.c b/sys/dev/crypto/tpm/tpm_crb.c
index 1111111..2222222 100644
--- a/sys/dev/crypto/tpm/tpm_crb.c
+++ b/sys/dev/crypto/tpm/tpm_crb.c
@@ -218,6 +218,33 @@
 		}
 	}
 
+	/*
+	 * Validate that the command and response buffers actually fit
+	 * within the allocated MMIO BAR.  The TPM reports these via CRB
+	 * registers; a buggy or malicious implementation (common with
+	 * software emulators) can report values that would cause OOB
+	 * bus_space accesses in tpmcrb_transmit.
+	 */
+	bus_size_t bar_size = rman_get_size(sc->mem_res);
+	if (crb_sc->cmd_off >= bar_size ||
+	    crb_sc->cmd_buf_size > bar_size - crb_sc->cmd_off) {
+		device_printf(sc->dev,
+		    "Command buffer exceeds BAR (off=0x%jx size=0x%jx bar=0x%jx)\n",
+		    (uintmax_t)crb_sc->cmd_off, (uintmax_t)crb_sc->cmd_buf_size,
+		    (uintmax_t)bar_size);
+		tpmcrb_detach(dev);
+		return (ENXIO);
+	}
+	if (crb_sc->rsp_off >= bar_size ||
+	    crb_sc->rsp_buf_size > bar_size - crb_sc->rsp_off) {
+		device_printf(sc->dev,
+		    "Response buffer exceeds BAR (off=0x%jx size=0x%jx bar=0x%jx)\n",
+		    (uintmax_t)crb_sc->rsp_off, (uintmax_t)crb_sc->rsp_buf_size,
+		    (uintmax_t)bar_size);
+		tpmcrb_detach(dev);
+		return (ENXIO);
+	}
+
 	sc->transmit = tpmcrb_transmit;
 
 	result = tpm20_init(sc);