[PATCH 32/64] drm/vc4: dsi: Fix the driver structure lifetime
Thomas Zimmermann
tzimmermann at suse.de
Mon Jun 20 10:59:45 UTC 2022
Am 20.06.22 um 12:55 schrieb Thomas Zimmermann:
>
>
> 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() ?
No, wait. That's the release function.
It's confusing. I'd rename vc4_dsi_put() to vc4_dsi_release_action() and
wrap those kref_get/kref_put calls in small helpers named
vc4_dsi_get/vc4_dsi_put. That's more aligned to the usual naming
conventions, I'd say.
Best regards
Thomas
>
>> 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/0ba7bcb0/attachment.sig>
More information about the dri-devel
mailing list