⬢ DragonFlyBSD Kernel Audit
DF-4372 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon.h	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/dev/drm/radeon/radeon.h	2026-09-19 18:44:48.361621795 +0000
@@ -2331,6 +2331,7 @@
 	int				disp_priority;
 	/* BIOS */
 	uint8_t				*bios;
+	size_t				bios_size;	/* size of the kmalloc'd *bios image */
 	bool				is_atom_bios;
 	uint16_t			bios_header_start;
 	struct radeon_bo		*stolen_vga_memory;
--- a/sys/dev/drm/radeon/radeon_bios.c	2026-07-22 23:04:24.341615154 +0000
+++ b/sys/dev/drm/radeon/radeon_bios.c	2026-09-19 18:44:48.361621795 +0000
@@ -66,6 +66,7 @@
 		return false;
 	}
 	rdev->bios = kmalloc(size, M_DRM, M_WAITOK);
+	rdev->bios_size = size;
 	if (rdev->bios == NULL) {
 		iounmap(bios);
 		return false;
@@ -96,6 +97,7 @@
 		return false;
 	}
 	rdev->bios = kzalloc(size, GFP_KERNEL);
+	rdev->bios_size = size;
 	if (rdev->bios == NULL) {
 		vga_pci_unmap_bios(vga_dev, bios);
 		return false;
@@ -151,6 +153,7 @@
 	}
 
 	rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+	rdev->bios_size = size;
 	pmap_unmapdev((vm_offset_t)bios, 256 * 1024);
 	pci_write_config(bsddev, PCIR_BIOS, saved_rom_bar, 4);
 
@@ -267,6 +270,7 @@
 		return false;
 
 	rdev->bios = kmalloc(size, M_DRM, M_WAITOK);
+	rdev->bios_size = size;
 	if (!rdev->bios) {
 		DRM_ERROR("Unable to allocate bios\n");
 		return false;
@@ -715,6 +719,7 @@
 	}
 
 	rdev->bios = kmalloc(vhdr->ImageLength, M_DRM, M_WAITOK);
+	rdev->bios_size = vhdr->ImageLength;
 	memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength);
 	ret = !!rdev->bios;
 
--- a/sys/dev/drm/radeon/r600_dpm.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/dev/drm/radeon/r600_dpm.c	2026-09-19 18:46:26.864362447 +0000
@@ -891,6 +891,15 @@
 	if (le16_to_cpu(power_info->pplib.usTableSize) >=
 	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
 		if (power_info->pplib3.usFanTableOffset) {
+			u32 fan_off = data_offset +
+				le16_to_cpu(power_info->pplib3.usFanTableOffset);
+
+			if (!rdev->bios_size ||
+			    fan_off + sizeof(union fan_info) > rdev->bios_size) {
+				DRM_ERROR("Invalid VBIOS fan table offset %u\n",
+					  fan_off);
+				return -EINVAL;
+			}
 			fan_info = (union fan_info *)((uint8_t*)mode_info->atom_context->bios + data_offset +
 						      le16_to_cpu(power_info->pplib3.usFanTableOffset));
 			rdev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
@@ -1067,10 +1076,15 @@
 	/* ext tables */
 	if (le16_to_cpu(power_info->pplib.usTableSize) >=
 	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
-		ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
-			(mode_info->atom_context->bios + data_offset +
-			 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
+		u32 ext_off = le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset);
+		bool ext_hdr_ok = ext_off != 0 && rdev->bios_size &&
+			((u64)data_offset + ext_off +
+			 sizeof(ATOM_PPLIB_EXTENDEDHEADER)) <= rdev->bios_size;
+		ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = ext_hdr_ok ?
+			(ATOM_PPLIB_EXTENDEDHEADER *)
+			(mode_info->atom_context->bios + data_offset + ext_off) : NULL;
+
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
 			ext_hdr->usVCETableOffset) {
 			VCEClockInfoArray *array = (VCEClockInfoArray *)
 				(mode_info->atom_context->bios + data_offset +
@@ -1132,7 +1146,7 @@
 					((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
 			}
 		}
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
 			ext_hdr->usUVDTableOffset) {
 			UVDClockInfoArray *array = (UVDClockInfoArray *)
 				(mode_info->atom_context->bios + data_offset +
@@ -1168,7 +1182,7 @@
 					((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
 			}
 		}
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
 			ext_hdr->usSAMUTableOffset) {
 			ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
 				(ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
@@ -1195,7 +1209,7 @@
 					((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
 			}
 		}
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
 		    ext_hdr->usPPMTableOffset) {
 			ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
 				(mode_info->atom_context->bios + data_offset +
@@ -1226,7 +1240,7 @@
 			rdev->pm.dpm.dyn_state.ppm_table->tj_max =
 				le32_to_cpu(ppm->ulTjmax);
 		}
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
 			ext_hdr->usACPTableOffset) {
 			ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
 				(ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
@@ -1253,7 +1267,7 @@
 					((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
 			}
 		}
-		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
+		if (ext_hdr_ok && (le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
 			ext_hdr->usPowerTuneTableOffset) {
 			u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
 					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));