⬢ DragonFlyBSD Kernel Audit
DF-3698 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c
index 1111111..3333333 100644
--- a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c
+++ b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c
@@ -934,8 +934,10 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
 	else
 		always_on_cu_num = 12;
 
+	/* cu_info->bitmap / ao_cu_bitmap are [4][4] (amdgpu_gfx.h) */
 	mutex_lock(&adev->grbm_idx_mutex);
-	for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-		for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+	for (i = 0; i < min(adev->gfx.config.max_shader_engines, 4u); i++) {
+		for (j = 0; j < min(adev->gfx.config.max_sh_per_se, 4u); j++) {
 			mask = 1;
 			cu_bitmap = 0;
 			counter = 0;
@@ -1457,6 +1459,15 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
 		break;
 	}
 
+	/*
+	 * gfx.config geometry may come from the gpu_info firmware file or the
+	 * VBIOS gfx_info table; neither is bounds-checked at parse time.
+	 * Clamp to the fixed [4][4] dimensions of struct amdgpu_cu_info so the
+	 * cu_info walkers cannot index out of bounds.
+	 */
+	adev->gfx.config.max_shader_engines =
+		min(adev->gfx.config.max_shader_engines, 4u);
+	adev->gfx.config.max_sh_per_se =
+		min(adev->gfx.config.max_sh_per_se, 4u);
+
 	adev->gfx.config.gb_addr_config = gb_addr_config;
 
 	adev->gfx.config.gb_addr_config_fields.num_pipes = 1 <<
@@ -4987,8 +4998,10 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
 	amdgpu_gfx_parse_disable_cu(disable_masks, 4, 2);
 
 	mutex_lock(&adev->grbm_idx_mutex);
-	for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-		for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+	/* cu_info->bitmap / ao_cu_bitmap are [4][4] (amdgpu_gfx.h) */
+	for (i = 0; i < min(adev->gfx.config.max_shader_engines, 4u); i++) {
+		for (j = 0; j < min(adev->gfx.config.max_sh_per_se, 4u); j++) {
 			mask = 1;
 			ao_bitmap = 0;
 			counter = 0;