DragonFlyBSD Kernel Audit
DF-2065 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/si_smc.c b/sys/dev/drm/radeon/si_smc.c
--- a/sys/dev/drm/radeon/si_smc.c
+++ b/sys/dev/drm/radeon/si_smc.c
@@ -258,6 +258,27 @@
 		src = (const u8 *)rdev->smc_fw->data;
 	}
 
+	/* Validate firmware-derived offsets/sizes against the blob and the SMC
+	 * SRAM limit before the write loop, to prevent heap OOB reads
+	 * (offset+size > datasize) and unbounded SMC SRAM writes
+	 * (start+size > limit). This makes the previously-dead `limit`
+	 * parameter actually bound the write, matching the bounds checks in
+	 * si_copy_bytes_to_smc() and si_set_smc_sram_address().
+	 */
+	if (rdev->new_fw) {
+		const struct smc_firmware_header_v1_0 *hdr =
+		    (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
+
+		if (le32_to_cpu(hdr->header.ucode_array_offset_bytes) + ucode_size >
+		    rdev->smc_fw->datasize) {
+			DRM_ERROR("SMC ucode read exceeds firmware blob size\n");
+			return -EINVAL;
+		}
+	}
+	if ((uint64_t)ucode_start_address + ucode_size > limit) {
+		DRM_ERROR("SMC ucode write exceeds SRAM limit\n");
+		return -EINVAL;
+	}
 	if (ucode_size & 3)
 		return -EINVAL;