Re: [PATCH] drm/msm/dp: Drop aux devices together with DP controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13/06/2023 01:01, Bjorn Andersson wrote:
Using devres to depopulate the aux bus made sure that upon a probe
deferral the EDP panel device would be destroyed and recreated upon next
attempt.

But the struct device which the devres is tied to is the DPUs
(drm_dev->dev), which may be happen after the DP controller is torn
down.

Indications of this can be seen in the commonly seen EDID-hexdump full
of zeros in the log, or the occasional/rare KASAN fault where the
panel's attempt to read the EDID information causes a use after free on
DP resources.

It's tempting to move the devres to the DP controller's struct device,
but the resources used by the device(s) on the aux bus are explicitly
torn down in the error path.

I hoped that proper usage of of_dp_aux_populate_bus(), with the callback function being non-NULL would have solved at least this part. But it seems I'll never see this patch.

The KASAN-reported use-after-free also
remains, as the DP aux "module" explicitly frees its devres-allocated
memory in this code path.

As such, explicitly depopulate the aux bus in the error path, and in the
component unbind path, to avoid these issues.

Fixes: 2b57f726611e ("drm/msm/dp: fix aux-bus EP lifetime")
Signed-off-by: Bjorn Andersson <quic_bjorande@xxxxxxxxxxx>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx>

---
  drivers/gpu/drm/msm/dp/dp_display.c | 14 +++-----------
  1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 3d8fa2e73583..bbb0550a022b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -322,6 +322,8 @@ static void dp_display_unbind(struct device *dev, struct device *master,
kthread_stop(dp->ev_tsk); + of_dp_aux_depopulate_bus(dp->aux);
+
  	dp_power_client_deinit(dp->power);
  	dp_unregister_audio_driver(dev, dp->audio);
  	dp_aux_unregister(dp->aux);
@@ -1521,11 +1523,6 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
  	}
  }
-static void of_dp_aux_depopulate_bus_void(void *data)
-{
-	of_dp_aux_depopulate_bus(data);
-}
-
  static int dp_display_get_next_bridge(struct msm_dp *dp)
  {
  	int rc;
@@ -1554,12 +1551,6 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
  		of_node_put(aux_bus);
  		if (rc)
  			goto error;
-
-		rc = devm_add_action_or_reset(dp->drm_dev->dev,
-						of_dp_aux_depopulate_bus_void,
-						dp_priv->aux);
-		if (rc)
-			goto error;
  	} else if (dp->is_edp) {
  		DRM_ERROR("eDP aux_bus not found\n");
  		return -ENODEV;
@@ -1583,6 +1574,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
error:
  	if (dp->is_edp) {
+		of_dp_aux_depopulate_bus(dp_priv->aux);
  		disable_irq(dp_priv->irq);
  		dp_display_host_phy_exit(dp_priv);
  		dp_display_host_deinit(dp_priv);

--
With best wishes
Dmitry




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux