DragonFlyBSD Kernel Audit
DF-1498 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.c b/sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.c
--- a/sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.c
@@ -1495,6 +1495,18 @@
 	if ((profile->asHeader.ucTableFormatRevision >= 2) &&
 		(profile->asHeader.ucTableContentRevision >= 1) &&
 		(profile->asHeader.usStructureSize >= sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))) {
+		/* Validate that all offsets fall inside the table to
+		 * prevent OOB reads of attacker-controlled BIOS data. */
+		if (profile->usLeakageBinArrayOffset +
+			(profile->ucLeakageBinNum * (uint32_t)sizeof(u16)) >
+		    le16_to_cpu(profile->asHeader.usStructureSize) ||
+		    profile->usElbVDDC_IdArrayOffset +
+			(profile->ucElbVDDC_Num * (uint32_t)sizeof(u16)) >
+		    le16_to_cpu(profile->asHeader.usStructureSize) ||
+		    profile->usElbVDDC_LevelArrayOffset +
+			(profile->ucElbVDDC_Num * profile->ucLeakageBinNum * (uint32_t)sizeof(u16)) >
+		    le16_to_cpu(profile->asHeader.usStructureSize))
+			return -EINVAL;
 		leakage_bin = (u16 *)((char *)profile + profile->usLeakageBinArrayOffset);
 		vddc_id_buf = (u16 *)((char *)profile + profile->usElbVDDC_IdArrayOffset);
 		vddc_buf = (u16 *)((char *)profile + profile->usElbVDDC_LevelArrayOffset);