The OPP reference obtained via dev_pm_opp_find_freq_ceil() is dropped
with dev_pm_opp_put() before being passed to dev_pm_opp_set_opp(). If
the reference count reaches zero, the OPP object may be freed, leading
to a use-after-free when dev_pm_opp_set_opp() dereferences it.

Fix the order of calls: first use the OPP to set the required
performance state, then release the reference.

Fixes: 5a903a44a984 ("drm/msm/a6xx: Introduce GMU wrapper support")
Signed-off-by: Roman Demidov <[email protected]>
---
v2: The dev_pm_opp_find_freq_ceil() function returns an OPP object with an
incremented reference count. Dropping this reference via dev_pm_opp_put()
could cause the object to be freed if it is concurrently removed from the
OPP table. Fix this as Sashiko AI <[email protected]> suggested.

 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index f9de9329dee3..c827986951cc 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2177,10 +2177,10 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
                ret = PTR_ERR(opp);
                goto err_set_opp;
        }
-       dev_pm_opp_put(opp);
 
        /* Set the core clock and bus bw, having VDD scaling in mind */
        dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
+       dev_pm_opp_put(opp);
 
        pm_runtime_resume_and_get(gmu->dev);
        pm_runtime_resume_and_get(gmu->gxpd);
-- 
2.53.0

Reply via email to