radeon: avoid double free in ci_dpm_init()
authorjsg <jsg@openbsd.org>
Thu, 20 Jul 2023 08:21:29 +0000 (08:21 +0000)
committerjsg <jsg@openbsd.org>
Thu, 20 Jul 2023 08:21:29 +0000 (08:21 +0000)
From Nikita Zhandarovich
cb86b0e3d9d38ba351dd10caef483529653dd481 in linux-6.1.y/6.1.39
20c3dffdccbd494e0dd631d1660aeecbff6775f2 in mainline linux

sys/dev/pci/drm/radeon/ci_dpm.c

index 8ef25ab..b8f4dac 100644 (file)
@@ -5517,6 +5517,7 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        u8 frev, crev;
        u8 *power_state_offset;
        struct ci_ps *ps;
+       int ret;
 
        if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
                                   &frev, &crev, &data_offset))
@@ -5546,11 +5547,15 @@ static int ci_parse_power_table(struct radeon_device *rdev)
                non_clock_array_index = power_state->v2.nonClockInfoIndex;
                non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
                        &non_clock_info_array->nonClockInfo[non_clock_array_index];
-               if (!rdev->pm.power_state[i].clock_info)
-                       return -EINVAL;
+               if (!rdev->pm.power_state[i].clock_info) {
+                       ret = -EINVAL;
+                       goto err_free_ps;
+               }
                ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
-               if (ps == NULL)
-                       return -ENOMEM;
+               if (ps == NULL) {
+                       ret = -ENOMEM;
+                       goto err_free_ps;
+               }
                rdev->pm.dpm.ps[i].ps_priv = ps;
                ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
                                              non_clock_info,
@@ -5590,6 +5595,12 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        }
 
        return 0;
+
+err_free_ps:
+       for (i = 0; i < rdev->pm.dpm.num_ps; i++)
+               kfree(rdev->pm.dpm.ps[i].ps_priv);
+       kfree(rdev->pm.dpm.ps);
+       return ret;
 }
 
 static int ci_get_vbios_boot_values(struct radeon_device *rdev,
@@ -5678,25 +5689,26 @@ int ci_dpm_init(struct radeon_device *rdev)
 
        ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state);
        if (ret) {
-               ci_dpm_fini(rdev);
+               kfree(rdev->pm.dpm.priv);
                return ret;
        }
 
        ret = r600_get_platform_caps(rdev);
        if (ret) {
-               ci_dpm_fini(rdev);
+               kfree(rdev->pm.dpm.priv);
                return ret;
        }
 
        ret = r600_parse_extended_power_table(rdev);
        if (ret) {
-               ci_dpm_fini(rdev);
+               kfree(rdev->pm.dpm.priv);
                return ret;
        }
 
        ret = ci_parse_power_table(rdev);
        if (ret) {
-               ci_dpm_fini(rdev);
+               kfree(rdev->pm.dpm.priv);
+               r600_free_extended_power_table(rdev);
                return ret;
        }