DragonFlyBSD Kernel Audit
DF-2015 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/vce_v1_0.c b/sys/dev/drm/radeon/vce_v1_0.c
--- a/sys/dev/drm/radeon/vce_v1_0.c
+++ b/sys/dev/drm/radeon/vce_v1_0.c
@@ -158,9 +158,18 @@
 int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data)
 {
 	const struct vce_v1_0_fw_signature *sign = (const void*)rdev->vce_fw->data;
-	uint32_t chip_id;
+	uint32_t chip_id, fw_num, fw_len, fw_datasize;
 	int i;
 
+	fw_datasize = rdev->vce_fw->datasize;
+	if (fw_datasize < sizeof(*sign))
+		return -EINVAL;
+	fw_num = le32_to_cpu(sign->num);
+	fw_len = le32_to_cpu(sign->len);
+	if (fw_num > 64 || fw_len > fw_datasize ||
+	    sizeof(*sign) + fw_num * sizeof(sign->val[0]) > fw_datasize)
+		return -EINVAL;
+
 	switch (rdev->family) {
 	case CHIP_TAHITI:
 		chip_id = 0x01000014;
@@ -195,7 +204,7 @@
 	data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64);
 
 	memset(&data[5], 0, 44);
-	memcpy(&data[16], &sign[1], rdev->vce_fw->datasize - sizeof(*sign));
+	memcpy(&data[16], &sign[1], min(fw_datasize - sizeof(*sign), (uint32_t)VCE_V1_0_DATA_SIZE));
 
 	data += (le32_to_cpu(sign->len) + 64) / 4;
 	data[0] = sign->val[i].sigval[0];