lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Thu,  7 Jul 2022 16:11:39 +0800
From:   Liang He <windhl@....com>
To:     linux-kernel@...r.kernel.org, windhl@....com
Subject: [PATCH] arm-cci: Fix refcount leak bugs

In fact, there are several bugs:

(1) In cci_probe(), we should call of_node_put() for the refernece
returned by of_find_matching_node() which has increased the refcount.

(2) In __cci_ace_get_port(), we should call of_node_put() in fail path
or when the reference is not used anymore as the reference is returned
by of_parse_phandle() which has increased the refcount.

(3) In cci_ace_init_ports(), we should call of_node_put() when the
referne is not used anymore as the of_get_cpu_node() will increase
the refcount.

(4) In cci_probe_ports(), we should call of_node_put() when breaking
out of for_each_available_child_of_node() which will automatically
increase and decrease refcount. Besides, we should also call
of_node_get() for the new reference created in 'ports[i].dn'.

Fixes: ed69bdd8fd9b ("drivers: bus: add ARM CCI support")
Signed-off-by: Liang He <windhl@....com>
---

 For bug(4), I have not found when the global 'ports' is destroyed,
so I cannot use 'of_node_put()' for its 'dn'. Please check it carefully.

 drivers/bus/arm-cci.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index b8184a903583..d8e66022de5c 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -167,9 +167,12 @@ static int __cci_ace_get_port(struct device_node *dn, int type)
 	cci_portn = of_parse_phandle(dn, "cci-control-port", 0);
 	for (i = 0; i < nb_cci_ports; i++) {
 		ace_match = ports[i].type == type;
-		if (ace_match && cci_portn == ports[i].dn)
+		if (ace_match && cci_portn == ports[i].dn) {
+			of_node_put(cci_portn);
 			return i;
+		}
 	}
+	of_node_put(cci_portn);
 	return -ENODEV;
 }
 
@@ -199,6 +202,7 @@ static void cci_ace_init_ports(void)
 			continue;
 
 		port = __cci_ace_get_port(cpun, ACE_PORT);
+		of_node_put(cpun);
 		if (port < 0)
 			continue;
 
@@ -461,8 +465,10 @@ static int cci_probe_ports(struct device_node *np)
 
 		i = nb_ace + nb_ace_lite;
 
-		if (i >= nb_cci_ports)
+		if (i >= nb_cci_ports) {
+			of_node_put(cp);
 			break;
+		}
 
 		if (of_property_read_string(cp, "interface-type",
 					&match_str)) {
@@ -498,7 +504,7 @@ static int cci_probe_ports(struct device_node *np)
 			ports[i].type = ACE_LITE_PORT;
 			++nb_ace_lite;
 		}
-		ports[i].dn = cp;
+		ports[i].dn = of_node_get(cp);
 	}
 
 	/*
@@ -551,7 +557,9 @@ static int cci_probe(void)
 		return -ENXIO;
 	}
 
-	return cci_probe_ports(np);
+	ret = cci_probe_ports(np);
+	of_node_put(np);
+	return ret;
 }
 
 static int cci_init_status = -EAGAIN;
-- 
2.25.1

Powered by blists - more mailing lists