DragonFlyBSD Kernel Audit
DF-1990 / 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
--- a/sys/dev/crypto/tpm/tpm_crb.c
+++ b/sys/dev/crypto/tpm/tpm_crb.c
@@ -308,7 +308,7 @@
 {
 	struct tpmcrb_sc *crb_sc;
 	uint32_t mask, curr_cmd;
-	int timeout, bytes_available;
+	int timeout, bytes_available, errval = 0;
 
 	crb_sc = (struct tpmcrb_sc *)sc;
 
@@ -342,7 +342,8 @@
 			    mask, mask, TPM_TIMEOUT_C)) {
 			device_printf(sc->dev,
 			    "Failed to transition to idle state\n");
-			return (EIO);
+			errval = EIO;
+			goto err_locality;
 		}
 	}
 	/* Switch to ready state */
@@ -353,7 +354,8 @@
 		    mask, !mask, TPM_TIMEOUT_C)) {
 		device_printf(sc->dev,
 		    "Failed to transition to ready state\n");
-		return (EIO);
+		errval = EIO;
+		goto err_locality;
 	}
 
 	/*
@@ -377,8 +379,10 @@
 	if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) {
 		device_printf(sc->dev,
 		    "Timeout while waiting for device to process cmd\n");
-		if (!tpmcrb_cancel_cmd(sc))
-			return (EIO);
+		if (!tpmcrb_cancel_cmd(sc)) {
+			errval = EIO;
+			goto err_locality;
+		}
 	}
 
 	/* Read response header. Length is passed in bytes 2 - 6. */
@@ -390,18 +394,21 @@
 		device_printf(sc->dev,
 		    "Incorrect response size: %d\n",
 		    bytes_available);
-		return (EIO);
+		errval = EIO;
+		goto err_locality;
 	}
 
 	bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
 	      &sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
 
+err_locality:
 	OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
 
 	tpmcrb_relinquish_locality(sc);
-	sc->pending_data_length = bytes_available;
+	if (errval == 0)
+		sc->pending_data_length = bytes_available;
 
-	return (0);
+	return (errval);
 }
 
 /* ACPI Driver */