]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
of/irq: Fix device node refcount leakage in API of_irq_parse_raw()
authorZijun Hu <quic_zijuhu@quicinc.com>
Sun, 9 Feb 2025 12:58:57 +0000 (20:58 +0800)
committerRob Herring (Arm) <robh@kernel.org>
Tue, 25 Feb 2025 13:16:50 +0000 (07:16 -0600)
if the node @out_irq->np got by of_irq_parse_raw() is a combo node which
consists of both controller and nexus, namely, of_irq_parse_raw() returns
due to condition (@ipar == @newpar), then the node's refcount was increased
twice, hence causes refcount leakage.

Fix by putting @out_irq->np refcount before returning due to the condition.
Also add comments about refcount of node @out_irq->np got by the API.

Fixes: 041284181226 ("of/irq: Allow matching of an interrupt-map local to an interrupt controller")
Cc: stable@vger.kernel.org
Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-4-93e3a2659aa7@quicinc.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
drivers/of/irq.c

index 95456e9186819746a11435a93af3aebead72da2d..1a018726fb0e815c895602e14c35c3a084434b73 100644 (file)
@@ -166,6 +166,8 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph
  * the specifier for each map, and then returns the translated map.
  *
  * Return: 0 on success and a negative number on error
+ *
+ * Note: refcount of node @out_irq->np is increased by 1 on success.
  */
 int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 {
@@ -311,6 +313,12 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                addrsize = (imap - match_array) - intsize;
 
                if (ipar == newpar) {
+                       /*
+                        * We got @ipar's refcount, but the refcount was
+                        * gotten again by of_irq_parse_imap_parent() via its
+                        * alias @newpar.
+                        */
+                       of_node_put(ipar);
                        pr_debug("%pOF interrupt-map entry to self\n", ipar);
                        return 0;
                }