* [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
@ 2026-09-04 7:34 Fuad Tabba
2026-09-04 7:48 ` sashiko-bot
0 siblings, 1 reply; 5+ messages in thread
From: Fuad Tabba @ 2026-09-04 7:34 UTC (permalink / raw)
To: Rob Herring, Saravana Kannan
Cc: Lorenzo Pieralisi, Frank Li, devicetree, linux-kernel, Fuad Tabba
of_msi_xlate() documents @msi_np as a filter when it points at a node on
entry, handing back a reference only when it points at NULL. The msi-map
branch does that. of_check_msi_parent() keeps the reference from the 1:1
msi-parent match either way.
pci_msi_domain_get_msi_rid() is the only caller that passes a node in,
from irq_domain_get_of_node(), and it puts nothing, so a 1:1 match there
leaks the MSI controller node.
Fixes: 119aaeed0b67 ("of/irq: Add msi-parent check to of_msi_xlate()")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260826113604.010C01F000E9@smtp.kernel.org/
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
drivers/of/irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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;
--
2.39.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
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
0 siblings, 1 reply; 5+ messages in thread
From: sashiko-bot @ 2026-09-04 7:48 UTC (permalink / raw)
To: Fuad Tabba; +Cc: conor+dt, devicetree, robh
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?
[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?
[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?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260904073424.3855365-1-fuad.tabba@linux.dev?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
2026-09-04 7:48 ` sashiko-bot
@ 2026-09-04 9:25 ` Fuad Tabba
2026-09-04 11:11 ` Lorenzo Pieralisi
0 siblings, 1 reply; 5+ messages in thread
From: Fuad Tabba @ 2026-09-04 9:25 UTC (permalink / raw)
To: sashiko-reviews; +Cc: conor+dt, devicetree, robh, Lorenzo Pieralisi
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?
>
> [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.
/fuad
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260904073424.3855365-1-fuad.tabba@linux.dev?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
2026-09-04 9:25 ` Fuad Tabba
@ 2026-09-04 11:11 ` Lorenzo Pieralisi
2026-09-04 12:48 ` Fuad Tabba
0 siblings, 1 reply; 5+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-04 11:11 UTC (permalink / raw)
To: Fuad Tabba; +Cc: sashiko-reviews, conor+dt, devicetree, robh
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] of/irq: Fix device node refcount leak in of_check_msi_parent()
2026-09-04 11:11 ` Lorenzo Pieralisi
@ 2026-09-04 12:48 ` Fuad Tabba
0 siblings, 0 replies; 5+ messages in thread
From: Fuad Tabba @ 2026-09-04 12:48 UTC (permalink / raw)
To: Lorenzo Pieralisi; +Cc: sashiko-reviews, conor+dt, devicetree, robh
On Fri, 4 Sept 2026 at 12:11, Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
...
> > 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).
Thanks for the clarification.
Cheers,
/fuad
> >
> > >
> > > [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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-04 12:48 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2026-09-04 12:48 ` Fuad Tabba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox