The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: <Balakrishnan.S@microchip.com>
To: <ehristev@kernel.org>, <mchehab@kernel.org>
Cc: <hverkuil@kernel.org>, <sakari.ailus@linux.intel.com>,
	<linux-media@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<stable@vger.kernel.org>
Subject: Re: [PATCH v4 02/10] media: microchip-isc: take a reference on the parsed endpoints
Date: Thu, 13 Aug 2026 05:25:36 +0000	[thread overview]
Message-ID: <145b878b-e66f-4bf9-bc22-567450dc13f5@microchip.com> (raw)
In-Reply-To: <1a936439-55e2-498d-96bb-d9c1a1083630@kernel.org>

Hi Eugen,

On 12/08/26 10:49 pm, Eugen Hristev wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 8/11/26 14:03, Balakrishnan.S@microchip.com wrote:
>> Hi Eugen,
>>
>> On 07/08/26 4:07 pm, Eugen Hristev wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> On 8/3/26 13:20, Balakrishnan Sambath wrote:
>>>> for_each_endpoint_of_node() drops the reference on the current node as
>>>> it advances. xisc_parse_dt() and isc_parse_dt() store the node in
>>>> subdev_entity->epn and release it later with of_node_put(), but never
>>>> took their own reference, so the stored pointer refers to an
>>>> already-released node. This underflows the refcount and can
>>>> use-after-free, reachable through the camera device tree overlay.
>>>>
>>>> Take a reference with of_node_get() when storing the node, and drop it
>>>> in microchip_isc_subdev_cleanup() so the entities the bind loop never
>>>> reaches on an early exit do not leak it.
>>>>
>>>> Fixes: c9aa973884a1 ("media: atmel: atmel-isc: add microchip-xisc driver")
>>>> Fixes: d6701f13bd07 ("media: atmel: Use v4l2_async_notifier_add_fwnode_remote_subdev")
>>>> Cc: stable@vger.kernel.org
>>>> Signed-off-by: Balakrishnan Sambath <balakrishnan.s@microchip.com>
>>>> ---
>>>>    drivers/media/platform/microchip/microchip-isc-base.c  |  6 ++++++
>>>>    .../media/platform/microchip/microchip-sama5d2-isc.c   | 18 ++++++++++++------
>>>>    .../media/platform/microchip/microchip-sama7g5-isc.c   | 18 ++++++++++++------
>>>>    3 files changed, 30 insertions(+), 12 deletions(-)
>>>>
>>>> diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c
>>>> index eebbcb28a7ee..ca4f3b5f58aa 100644
>>>> --- a/drivers/media/platform/microchip/microchip-isc-base.c
>>>> +++ b/drivers/media/platform/microchip/microchip-isc-base.c
>>>> @@ -1853,6 +1853,12 @@ void microchip_isc_subdev_cleanup(struct isc_device *isc)
>>>>         list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
>>>>                 v4l2_async_nf_unregister(&subdev_entity->notifier);
>>>>                 v4l2_async_nf_cleanup(&subdev_entity->notifier);
>>>> +             /*
>>>> +              * Release the endpoint reference taken while parsing. It is
>>>> +              * NULL for entities the bind loop already consumed, so this
>>>> +              * only drops the ones left over on an early exit.
>>>> +              */
>>>> +             of_node_put(subdev_entity->epn);
>>>>         }
>>>>
>>>>         INIT_LIST_HEAD(&isc->subdev_entities);
>>>> diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
>>>> index 25d241b4c66a..532f2b50e2ea 100644
>>>> --- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
>>>> +++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
>>>> @@ -357,28 +357,28 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
>>>>         struct device_node *epn;
>>>>         struct isc_subdev_entity *subdev_entity;
>>>>         unsigned int flags;
>>>> +     int ret;
>>>>
>>>>         INIT_LIST_HEAD(&isc->subdev_entities);
>>>>
>>>>         for_each_endpoint_of_node(np, epn) {
>>>>                 struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
>>>> -             int ret;
>>>>
>>>>                 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
>>>>                                                  &v4l2_epn);
>>>>                 if (ret) {
>>>> -                     of_node_put(epn);
>>>>                         dev_err(dev, "Could not parse the endpoint\n");
>>>> -                     return -EINVAL;
>>>> +                     ret = -EINVAL;
>>>> +                     goto err_put;
>>>>                 }
>>>>
>>>>                 subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
>>>>                                              GFP_KERNEL);
>>>>                 if (!subdev_entity) {
>>>> -                     of_node_put(epn);
>>>> -                     return -ENOMEM;
>>>> +                     ret = -ENOMEM;
>>>> +                     goto err_put;
>>>>                 }
>>>> -             subdev_entity->epn = epn;
>>>> +             subdev_entity->epn = of_node_get(epn);
>>>>
>>>>                 flags = v4l2_epn.bus.parallel.flags;
>>>>
>>>> @@ -399,6 +399,12 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
>>>>         }
>>>>
>>>>         return 0;
>>>> +
>>>> +err_put:
>>>> +     of_node_put(epn);
>>>> +     list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
>>>> +             of_node_put(subdev_entity->epn);
>>>> +     return ret;
>>>>    }
>>>>
>>>>    static int microchip_isc_probe(struct platform_device *pdev)
>>>> diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
>>>> index 998146adabd8..0b72a61b51ee 100644
>>>> --- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
>>>> +++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
>>>> @@ -341,6 +341,7 @@ static int xisc_parse_dt(struct device *dev, struct isc_device *isc)
>>>>         struct isc_subdev_entity *subdev_entity;
>>>>         unsigned int flags;
>>>>         bool mipi_mode;
>>>> +     int ret;
>>>>
>>>>         INIT_LIST_HEAD(&isc->subdev_entities);
>>>>
>>>> @@ -348,23 +349,22 @@ static int xisc_parse_dt(struct device *dev, struct isc_device *isc)
>>>>
>>>>         for_each_endpoint_of_node(np, epn) {
>>>>                 struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
>>>> -             int ret;
>>>>
>>>>                 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
>>>>                                                  &v4l2_epn);
>>>>                 if (ret) {
>>>> -                     of_node_put(epn);
>>>>                         dev_err(dev, "Could not parse the endpoint\n");
>>>> -                     return -EINVAL;
>>>> +                     ret = -EINVAL;
>>>> +                     goto err_put;
>>>>                 }
>>>>
>>>>                 subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
>>>>                                              GFP_KERNEL);
>>>>                 if (!subdev_entity) {
>>>> -                     of_node_put(epn);
>>>> -                     return -ENOMEM;
>>>> +                     ret = -ENOMEM;
>>>> +                     goto err_put;
>>>>                 }
>>>> -             subdev_entity->epn = epn;
>>>> +             subdev_entity->epn = of_node_get(epn);
>>>>
>>>>                 flags = v4l2_epn.bus.parallel.flags;
>>>>
>>>> @@ -388,6 +388,12 @@ static int xisc_parse_dt(struct device *dev, struct isc_device *isc)
>>>>         }
>>>>
>>>>         return 0;
>>>> +
>>>> +err_put:
>>>> +     of_node_put(epn);
>>>
>>> epn is used for the iterator right ? Why calling put here outside of the
>>> iterator ?
>>> Even if the code is duplicated it makes more sense for me to cleanup
>>> inside the iterator.
>>> Outside the iterator the epn should be unused, at least my take on it.
>>
>> Sure, let me move the put inside the loop at each failure site so epn is
>> not touched after it. My intention with the err_put label was only to
>> avoid repeating it.
>>>
>>>> +     list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
>>>> +             of_node_put(subdev_entity->epn);
>>>
>>> Does it make sense to remove the entities from the list as well , aka
>>> cleanup the list ?
>>
>> subdev_entity is devm_kzalloc'd and the list head lives in isc, so both
>> are freed when probe fails so I felt a list_del is not really needed
>> here. Happy to add it though if you prefer having it makes the unwind clean.
>>
>> Please let me know your thoughts ?
> 
> I guess it's fine if you leave it like that. If others have any other
> opinion, please shout.

Noted. Thanks for the insight.

Thanks,
Balakrishnan

> 
> Eugen
> 
>>
>> Thanks,
>> Balakrishnan
>>>
>>>> +     return ret;
>>>>    }
>>>>
>>>>    static int microchip_xisc_probe(struct platform_device *pdev)
>>>>
>>>
>>
> 


  reply	other threads:[~2026-08-13  5:25 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-03 10:20 [PATCH v4 00/10] media: microchip-isc: AWB, stream-stop and endpoint-ref fixes Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 01/10] media: microchip-isc: fix awb_mutex and lock lifecycle Balakrishnan Sambath
2026-08-05  6:19   ` Eugen Hristev
2026-08-03 10:20 ` [PATCH v4 02/10] media: microchip-isc: take a reference on the parsed endpoints Balakrishnan Sambath
2026-08-07 10:37   ` Eugen Hristev
2026-08-11 11:03     ` Balakrishnan.S
2026-08-12 17:19       ` Eugen Hristev
2026-08-13  5:25         ` Balakrishnan.S [this message]
2026-08-03 10:20 ` [PATCH v4 03/10] media: microchip-isc: synchronize the IRQ before disabling clocks on stop Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 04/10] media: microchip-isc: disable histogram and flush AWB work on teardown Balakrishnan Sambath
2026-08-06  6:26   ` Eugen Hristev
2026-08-11 11:25     ` Balakrishnan.S
2026-08-03 10:20 ` [PATCH v4 05/10] media: microchip-isc: do not touch WB registers when not streaming Balakrishnan Sambath
2026-08-07 10:42   ` Eugen Hristev
2026-08-03 10:20 ` [PATCH v4 06/10] media: microchip-isc: store the unshifted PFE_CFG0 BPS value Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 07/10] media: microchip-isc: fix ISC_PFG_CFG0_BPS macro name typo Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 08/10] media: microchip-isc: fix PM runtime leak in AWB work handler Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 09/10] media: microchip-isc: fix SBGGR10 Bayer pattern Balakrishnan Sambath
2026-08-03 10:20 ` [PATCH v4 10/10] media: microchip-isc: fix WB offset and gain register field masking Balakrishnan Sambath
2026-08-05  6:17   ` Eugen Hristev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=145b878b-e66f-4bf9-bc22-567450dc13f5@microchip.com \
    --to=balakrishnan.s@microchip.com \
    --cc=ehristev@kernel.org \
    --cc=hverkuil@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=sakari.ailus@linux.intel.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox