DragonFlyBSD Kernel Audit
DF-2203 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/amdgpu/amdgpu_xgmi.c b/sys/dev/drm/amd/amdgpu/amdgpu_xgmi.c
index 0000000..1111111 100644
--- a/sys/dev/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/sys/dev/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -83,8 +83,27 @@
 		goto exit;
 
 	list_add_tail(&adev->gmc.xgmi.head, &hive->device_list);
-	list_for_each_entry(entry, &hive->device_list, head)
+	list_for_each_entry(entry, &hive->device_list, head) {
+		/*
+		 * DF-2203: tmp_topology is fixed-size
+		 * (AMDGPU_MAX_XGMI_DEVICE_PER_HIVE entries).  Without this
+		 * bound the write at tmp_topology[count++] smashes the
+		 * stack once the hive aggregates more devices than the
+		 * array holds (the stub psp_v11_0_xgmi_get_hive_id returns
+		 * the same constant id for every Vega20 GPU, so all of them
+		 * land in one hive).
+		 */
+		if (count >= AMDGPU_MAX_XGMI_DEVICE_PER_HIVE) {
+			dev_err(adev->dev,
+				"XGMI: hive %llx holds more than %d devices; "
+				"refusing to overflow tmp_topology",
+				adev->gmc.xgmi.hive_id,
+				AMDGPU_MAX_XGMI_DEVICE_PER_HIVE);
+			ret = -ENOSPC;
+			goto exit;
+		}
 		tmp_topology[count++].device_id = entry->device_id;
+	}
 
 	ret = psp_xgmi_get_topology_info(&adev->psp, count, tmp_topology);
 	if (ret) {