[PATCH 32/64] drm/vc4: dsi: Fix the driver structure lifetime
Thomas Zimmermann
tzimmermann at suse.de
Mon Jun 20 10:55:25 UTC 2022
Am 10.06.22 um 11:28 schrieb Maxime Ripard:
> The vc4_dsi structure is currently allocated through a device-managed
> allocation. This can lead to use-after-free issues however in the unbinding
> path since the DRM entities will stick around, but the underlying structure
> has been freed.
>
> However, we can't just fix it by using a DRM-managed allocation like we did
> for the other drivers since the DSI case is a bit more intricate.
>
> Indeed, the structure will be allocated at probe time, when we don't have a
> DRM device yet, to be able to register the DSI bus driver. We will then
> reuse it at bind time to register our KMS entities in the framework.
>
> In order to work around both constraints, we can use a kref to track the
> users of the structure (DSI host, and KMS), and then put our structure when
> the DSI host will have been unregistered, and through a DRM-managed action
> that will execute once we won't need the KMS entities anymore.
>
> Signed-off-by: Maxime Ripard <maxime at cerno.tech>
> ---
> drivers/gpu/drm/vc4/vc4_dsi.c | 29 ++++++++++++++++++++++++++++-
> 1 file changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index 10533a2a41b3..282537f27b8e 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -510,6 +510,8 @@ struct vc4_dsi {
> struct vc4_encoder encoder;
> struct mipi_dsi_host dsi_host;
>
> + struct kref kref;
> +
> struct platform_device *pdev;
>
> struct drm_bridge *bridge;
> @@ -1479,6 +1481,15 @@ vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi)
> dsi->clk_onecell);
> }
>
> +static void vc4_dsi_release(struct kref *kref);
> +
> +static void vc4_dsi_put(struct drm_device *drm, void *ptr)
> +{
> + struct vc4_dsi *dsi = ptr;
> +
> + kref_put(&dsi->kref, &vc4_dsi_release);
> +}
> +
> static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
> {
> struct platform_device *pdev = to_platform_device(dev);
> @@ -1488,6 +1499,12 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
> dma_cap_mask_t dma_mask;
> int ret;
>
> + kref_get(&dsi->kref);
> +
> + ret = drmm_add_action_or_reset(drm, vc4_dsi_put, dsi);
> + if (ret)
> + return ret;
> +
> dsi->variant = of_device_get_match_data(dev);
>
> INIT_LIST_HEAD(&dsi->bridge_chain);
> @@ -1642,16 +1659,25 @@ static const struct component_ops vc4_dsi_ops = {
> .unbind = vc4_dsi_unbind,
> };
>
> +static void vc4_dsi_release(struct kref *kref)
> +{
> + struct vc4_dsi *dsi =
> + container_of(kref, struct vc4_dsi, kref);
> +
> + kfree(dsi);
> +}
> +
> static int vc4_dsi_dev_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> struct vc4_dsi *dsi;
>
> - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
> + dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
> if (!dsi)
> return -ENOMEM;
> dev_set_drvdata(dev, dsi);
>
> + kref_init(&dsi->kref);
> dsi->pdev = pdev;
> dsi->dsi_host.ops = &vc4_dsi_host_ops;
> dsi->dsi_host.dev = dev;
> @@ -1666,6 +1692,7 @@ static int vc4_dsi_dev_remove(struct platform_device *pdev)
> struct vc4_dsi *dsi = dev_get_drvdata(dev);
>
> mipi_dsi_host_unregister(&dsi->dsi_host);
> + kref_put(&dsi->kref, &vc4_dsi_release);
Maybe vc4_dsi_put() ?
> return 0;
> }
>
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20220620/a91c5ad8/attachment.sig>
More information about the dri-devel
mailing list