⬢ DragonFlyBSD Kernel Audit
DF-4735 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/powermng/coretemp/coretemp.c
+++ b/sys/dev/powermng/coretemp/coretemp.c
@@ -133,7 +133,7 @@
 static int	coretemp_attach(device_t dev);
 static int	coretemp_detach(device_t dev);
 
-static void	coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr,
+static int	coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr,
 		    uint64_t *pkg_msr);
 static int	coretemp_msr_temp(struct coretemp_softc *sc, uint64_t msr);
 static void	coretemp_sensor_update(struct coretemp_softc *sc, int temp);
@@ -589,16 +589,30 @@
 	return temp;
 }
 
-static void
+static int
 coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr, uint64_t *pkg_msr)
 {
+	int error;
+
 	KASSERT(sc->sc_cpu == mycpuid,
 	    ("%s not on the target cpu%d, but on %d",
 	     device_get_name(sc->sc_dev), sc->sc_cpu, mycpuid));
 
-	*msr = rdmsr(MSR_THERM_STATUS);
-	if (pkg_msr != NULL)
-		*pkg_msr = rdmsr(MSR_PKG_THERM_STATUS);
+	/*
+	 * NB: some CPUs and VMMs advertise the CPUID thermal/DTS bits
+	 * without actually implementing the MSRs (see the PIII comment
+	 * in coretemp_identify()).  Use the fault-safe read so a lying
+	 * CPUID degrades to an invalid sensor instead of a kernel #GP.
+	 */
+	error = rdmsr_safe(MSR_THERM_STATUS, msr);
+	if (error)
+		return error;
+	if (pkg_msr != NULL) {
+		error = rdmsr_safe(MSR_PKG_THERM_STATUS, pkg_msr);
+		if (error)
+			return error;
+	}
+	return 0;
 }
 
 static void
@@ -647,7 +661,10 @@
 	uint64_t msr;
 	int temp;
 
-	coretemp_msr_fetch(sc, &msr, NULL);
+	if (coretemp_msr_fetch(sc, &msr, NULL) != 0) {
+		coretemp_sensor_update(sc, CORETEMP_TEMP_INVALID);
+		return;
+	}
 	temp = coretemp_msr_temp(sc, msr);
 
 	coretemp_sensor_update(sc, temp);
@@ -660,7 +677,11 @@
 	uint64_t msr, pkg_msr;
 	int temp, pkg_temp;
 
-	coretemp_msr_fetch(sc, &msr, &pkg_msr);
+	if (coretemp_msr_fetch(sc, &msr, &pkg_msr) != 0) {
+		coretemp_sensor_update(sc, CORETEMP_TEMP_INVALID);
+		coretemp_pkg_sensor_update(sc, CORETEMP_TEMP_INVALID);
+		return;
+	}
 	temp = coretemp_msr_temp(sc, msr);
 	pkg_temp = coretemp_pkg_msr_temp(sc, pkg_msr);