FAILED: patch "[PATCH] of/irq: Fix device node refcount leakage in API" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 0cb58d6c7b558a69957fabe159bfb184196e1e8d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025041730-pointed-lived-89e3@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0cb58d6c7b558a69957fabe159bfb184196e1e8d Mon Sep 17 00:00:00 2001
From: Zijun Hu <[email protected]>
Date: Sun, 9 Feb 2025 20:58:55 +0800
Subject: [PATCH] of/irq: Fix device node refcount leakage in API
of_irq_parse_one()
of_irq_parse_one(@int_gen_dev, i, ...) will leak refcount of @i_th_phandle
int_gen_dev {
...
interrupts-extended = ..., <&i_th_phandle ...>, ...;
...
};Refcount of @i_th_phandle is increased by of_parse_phandle_with_args() but is not decreased by API of_irq_parse_one() before return, so causes refcount leakage.
Rework the refcounting to use __free() cleanup and simplify the code to have a single call to of_irq_parse_raw().
Also add comments about refcount of node @out_irq->np got by the API.
drivers/of/irq.c +26 -31
@@ -16,6 +16,7 @@#define pr_fmt (fmt) "OF: " fmt +#include <linux/cleanup.h> #include <linux/device.h> #include <linux/errno.h> #include <linux/list.h>
@@ -339,10 +340,12 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);* This function resolves an interrupt for a node by walking the interrupt tree, * finding which interrupt controller node it is attached to, and returning the * interrupt specifier that can be used to retrieve a Linux IRQ number. +* +* Note: refcount of node @out_irq->np is increased by 1 on success. */ int of_irq_parse_one (struct device_node *device,int index,struct of_phandle_args *out_irq) { -struct device_node *p; + struct device_node __free(device_node) *p = NULL;const __be32 *addr;u32 intsize;int i, res, addr_len;
@@ -367,41 +370,33 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar/* Try the new-style interrupts-extended first */ res =of_parse_phandle_with_args (device,"interrupts-extended" ,"#interrupt-cells" , index, out_irq); -if (!res) -return of_irq_parse_raw (addr_buf, out_irq); +if (!res) { + p = out_irq->np; + }else { +/* Look for the interrupt parent. */ + p =of_irq_find_parent (device); +/* Get size of interrupt specifier */ +if (!p ||of_property_read_u32 (p,"#interrupt-cells" , &intsize)) +return -EINVAL ; -/* Look for the interrupt parent. */ - p =of_irq_find_parent (device); -if (p ==NULL ) -return -EINVAL ; +pr_debug (" parent=%pOF, intsize=%d\n" , p, intsize); -/* Get size of interrupt specifier */ -if (of_property_read_u32 (p,"#interrupt-cells" , &intsize)) { - res = -EINVAL ; - goto out; +/* Copy intspec into irq structure */ + out_irq->np = p; + out_irq->args_count = intsize; +for (i =0 ; i < intsize; i++) { + res =of_property_read_u32_index (device,"interrupts" , + (index * intsize) + i, + out_irq->args + i); +if (res) +return res; + } + +pr_debug (" intspec=%d\n" , *out_irq->args); } -pr_debug (" parent=%pOF, intsize=%d\n" , p, intsize); - -/* Copy intspec into irq structure */ - out_irq->np = p; - out_irq->args_count = intsize; -for (i =0 ; i < intsize; i++) { - res =of_property_read_u32_index (device,"interrupts" , - (index * intsize) + i, - out_irq->args + i); -if (res) - goto out; - } - -pr_debug (" intspec=%d\n" , *out_irq->args); - -/* Check if there are any interrupt-map translations to process */ - res =of_irq_parse_raw (addr_buf, out_irq); - out: -of_node_put (p); -return res; +return of_irq_parse_raw (addr_buf, out_irq); }EXPORT_SYMBOL_GPL (of_irq_parse_one);