Commit 7cce81df authored by Weigang He's avatar Weigang He Committed by Miquel Raynal
Browse files

mtd: parsers: ofpart: fix OF node refcount leak in parse_fixed_partitions()



of_get_child_by_name() returns a node pointer with refcount incremented,
which must be released with of_node_put() when done. However, in
parse_fixed_partitions(), when dedicated is true (i.e., a "partitions"
subnode was found), the ofpart_node obtained from of_get_child_by_name()
is never released on any code path.

Add of_node_put(ofpart_node) calls on all exit paths when dedicated is
true to fix the reference count leak.

This bug was detected by our static analysis tool.

Fixes: 562b4e91 ("mtd: parsers: ofpart: fix parsing subpartitions")
Signed-off-by: default avatarWeigang He <geoffreyhe2@gmail.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parent 68cd8ef4
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ static int parse_fixed_partitions(struct mtd_info *master,
	of_id = of_match_node(parse_ofpart_match_table, ofpart_node);
	if (dedicated && !of_id) {
		/* The 'partitions' subnode might be used by another parser */
		of_node_put(ofpart_node);
		return 0;
	}

@@ -95,12 +96,18 @@ static int parse_fixed_partitions(struct mtd_info *master,
		nr_parts++;
	}

	if (nr_parts == 0)
	if (nr_parts == 0) {
		if (dedicated)
			of_node_put(ofpart_node);
		return 0;
	}

	parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
	if (!parts)
	if (!parts) {
		if (dedicated)
			of_node_put(ofpart_node);
		return -ENOMEM;
	}

	i = 0;
	for_each_child_of_node(ofpart_node,  pp) {
@@ -179,6 +186,9 @@ static int parse_fixed_partitions(struct mtd_info *master,
	if (quirks && quirks->post_parse)
		quirks->post_parse(master, parts, nr_parts);

	if (dedicated)
		of_node_put(ofpart_node);

	*pparts = parts;
	return nr_parts;

@@ -187,6 +197,8 @@ static int parse_fixed_partitions(struct mtd_info *master,
	       master->name, pp, mtd_node);
	ret = -EINVAL;
ofpart_none:
	if (dedicated)
		of_node_put(ofpart_node);
	of_node_put(pp);
	kfree(parts);
	return ret;