All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Pieralisi <lpieralisi@kernel.org>
To: Fuad Tabba <fuad.tabba@linux.dev>
Cc: sashiko-reviews@lists.linux.dev, conor+dt@kernel.org,
	devicetree@vger.kernel.org, robh@kernel.org
Subject: Re: [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
Date: Fri, 4 Sep 2026 13:11:36 +0200	[thread overview]
Message-ID: <apqnaNmeuUjfC8Ng@red-moon> (raw)
In-Reply-To: <CA+EHjTx6ZC90qHoccTE6CLvGvxrXBe3Ph0bFKcgBvfRpCCAVuA@mail.gmail.com>

On Fri, Sep 04, 2026 at 10:25:24AM +0100, Fuad Tabba wrote:
> On Fri, 4 Sept 2026 at 08:48, <sashiko-bot@kernel.org> wrote:
> >
> > Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> >
> > Pre-existing issues:
> > - [High] of_msi_xlate() fails to traverse the device hierarchy when msi_np is NULL, completely breaking MSI ID mapping for callers such as the fsl-mc subsystem.
> > - [High] msi_node reference is leaked on error path in its_v5_pci_msi_prepare()
> > - [High] of_msi_xlate() incorrectly handles 'msi-parent' by continuing tree traversal when it mismatches.
> > --
> >
> > commit b8991c82a3994d7ebf04943226ad5d1d9490a8d4
> > Author: Fuad Tabba <fuad.tabba@linux.dev>
> >
> > of/irq: Fix device node refcount leak in of_check_msi_parent()
> >
> > The patch fixes a device node refcount leak in of_check_msi_parent(). It
> > ensures that if the node was not matched in a 1:1 mapping, the reference is
> > released correctly before returning.
> >
> > Link: https://lore.kernel.org/all/20260826113604.010C01F000E9@smtp.kernel.org/
> >
> > > diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> > > index ec035367c9500..109c54f346479 100644
> > > --- a/drivers/of/irq.c
> > > +++ b/drivers/of/irq.c
> > > @@ -785,7 +785,7 @@ static int of_check_msi_parent(struct device_node *dev_node, struct device_node
> > >       if ((*msi_node && *msi_node != msi_spec.np) || msi_spec.args_count != 0)
> > >               ret = -EINVAL;
> > >
> > > -     if (!ret) {
> > > +     if (!ret && !*msi_node) {
> > >               /* Return with a node reference held */
> > >               *msi_node = msi_spec.np;
> > >               return 0;
> >
> > [Severity: High]
> > This isn't a bug introduced by this patch, but of_msi_xlate() seems to
> > incorrectly handle msi-parent mismatches.
> >
> > If a device specifies an msi-parent that does not match the msi_np filter,
> > of_check_msi_parent() returns -EINVAL.
> >
> > drivers/of/irq.c:of_msi_xlate() {
> >                 /* -ENODEV: msi-map absent -> check for msi-parent */
> >                 if (msi_np && !of_check_msi_parent(parent_dev->of_node, msi_np))
> >                         break;
> > }
> >
> > The condition !of_check_msi_parent() evaluates to false, skipping the break
> > statement and allowing traversal to continue. Will this erroneously allow
> > traversal up the tree, potentially inheriting an incorrect msi-map from a
> > parent bus?
> 
> It does continue. -EINVAL also covers #msi-cells != 0, so
> of_msi_xlate() cannot tell a phandle mismatch from an msi-parent that
> is not a 1:1 mapping, and breaking on it would stop the walk for both.
> 
> Lorenzo, Rob, should the walk stop at the first node declaring an msi-parent?

First off, thank you for fixing this.

I think we must stop at the first msi-parent and apply the same (convoluted)
logic that of_msi_xlate() executes upon of_map_msi_id()'s return to make
sure ref counts are kosher (we already have an msi_spec scratch variable,
we can pass that to of_check_msi_parent() - that is, always drop the
msi_spec.np reference if !NULL and get one if !*msi_np to initialize it).

> 
> >
> > [Severity: High]
> > This is a pre-existing issue, but does of_msi_xlate() fail to traverse the
> > device hierarchy when msi_np is NULL?
> >
> > When of_map_msi_id() (which calls of_map_id()) processes an absent map
> > property while filter_np is NULL, it returns 0 instead of an error:
> >
> > drivers/of/base.c:of_map_id() {
> >         ...
> >         map = of_get_property(np, map_name, &map_bytes);
> >         if (!map) {
> >                 if (filter_np)
> >                         return -ENODEV;
> >                 /* Otherwise, no map implies no translation */
> >                 arg->args[0] = id;
> >                 arg->args_count = 1;
> >                 return 0;
> >         }
> >         ...
> > }
> >
> > In of_msi_xlate(), this return value of 0 triggers a break:
> >
> > drivers/of/irq.c:of_msi_xlate() {
> >                 if (!of_map_msi_id(parent_dev->of_node, id_in, msi_np, &msi_spec)) {
> >                         ...
> >                         /* msi-map present but no match -> stop walking */
> >                         break;
> >                 }
> > }
> >
> > Because of_map_id() returns 0 when the map is absent, wouldn't this early
> > break erroneously abort the parent traversal loop on the first iteration,
> > breaking MSI ID mapping for callers passing a NULL msi_np?
> 
> It does break early there, but not for fsl-mc, the only NULL caller:
> AFAICT, an fsl_mc_device never gets an of_node, so the walk carries on
> up to the fsl-mc platform device, which is where fsl,qoriq-mc puts
> msi-map.
> 
> > [Severity: High]
> > This isn't a bug introduced by this patch, but is there a fwnode reference
> > leak on the error path in its_v5_pci_msi_prepare()?
> >
> > drivers/irqchip/irq-gic-its-msi-parent.c:its_v5_pci_msi_prepare() {
> >         rid = pci_msi_map_rid_ctlr_node(domain->parent, pdev, &msi_node);
> >         if (!msi_node)
> >                 return -ENODEV;
> >
> >         ret = its_translate_frame_address(msi_node, &pa);
> >         if (ret)
> >                 return -ENODEV;
> >
> >         fwnode_handle_put(msi_node);
> >         ...
> > }
> >
> > If its_translate_frame_address() fails, it returns -ENODEV without dropping
> > the acquired msi_node reference. Can this leak the fwnode_handle if the
> > frame address translation fails repeatedly during driver bind or unbind?
> 
> Yes, every failed translation leaks one. I have a patch written,
> moving the put above the error check. It goes with the irqchip fixes
> rather than here.

Yep.

Thanks,
Lorenzo

  reply	other threads:[~2026-09-04 11:11 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04  7:34 [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent() Fuad Tabba
2026-09-04  7:48 ` sashiko-bot
2026-09-04  9:25   ` Fuad Tabba
2026-09-04 11:11     ` Lorenzo Pieralisi [this message]
2026-09-04 12:48       ` Fuad Tabba
2026-09-07  9:58         ` Lorenzo Pieralisi
2026-09-07 10:43           ` Fuad Tabba

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=apqnaNmeuUjfC8Ng@red-moon \
    --to=lpieralisi@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=fuad.tabba@linux.dev \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.