Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0773dcee authored by Frank Rowand's avatar Frank Rowand Committed by Greg Kroah-Hartman
Browse files

of: overlay: add_changeset_property() memory leak



[ Upstream commit 637392a8506a3a7dd24ab9094a14f7522adb73b4 ]

No changeset entries are created for #address-cells and #size-cells
properties, but the duplicated properties are never freed.  This
results in a memory leak which is detected by kmemleak:

 unreferenced object 0x85887180 (size 64):
   backtrace:
     kmem_cache_alloc_trace+0x1fb/0x1fc
     __of_prop_dup+0x25/0x7c
     add_changeset_property+0x17f/0x370
     build_changeset_next_level+0x29/0x20c
     of_overlay_fdt_apply+0x32b/0x6b4
     ...

Fixes: 6f75118800ac ("of: overlay: validate overlay properties #address-cells and #size-cells")
Reported-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: default avatarFrank Rowand <frank.rowand@sony.com>
Tested-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 0809e108
Loading
Loading
Loading
Loading
+20 −17
Original line number Diff line number Diff line
@@ -305,7 +305,6 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
{
	struct property *new_prop = NULL, *prop;
	int ret = 0;
	bool check_for_non_overlay_node = false;

	if (target->in_livetree)
		if (!of_prop_cmp(overlay_prop->name, "name") ||
@@ -318,6 +317,25 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
	else
		prop = NULL;

	if (prop) {
		if (!of_prop_cmp(prop->name, "#address-cells")) {
			if (!of_prop_val_eq(prop, overlay_prop)) {
				pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
				       target->np);
				ret = -EINVAL;
			}
			return ret;

		} else if (!of_prop_cmp(prop->name, "#size-cells")) {
			if (!of_prop_val_eq(prop, overlay_prop)) {
				pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
				       target->np);
				ret = -EINVAL;
			}
			return ret;
		}
	}

	if (is_symbols_prop) {
		if (prop)
			return -EINVAL;
@@ -330,33 +348,18 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
		return -ENOMEM;

	if (!prop) {
		check_for_non_overlay_node = true;
		if (!target->in_livetree) {
			new_prop->next = target->np->deadprops;
			target->np->deadprops = new_prop;
		}
		ret = of_changeset_add_property(&ovcs->cset, target->np,
						new_prop);
	} else if (!of_prop_cmp(prop->name, "#address-cells")) {
		if (!of_prop_val_eq(prop, new_prop)) {
			pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
			       target->np);
			ret = -EINVAL;
		}
	} else if (!of_prop_cmp(prop->name, "#size-cells")) {
		if (!of_prop_val_eq(prop, new_prop)) {
			pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
			       target->np);
			ret = -EINVAL;
		}
	} else {
		check_for_non_overlay_node = true;
		ret = of_changeset_update_property(&ovcs->cset, target->np,
						   new_prop);
	}

	if (check_for_non_overlay_node &&
	    !of_node_check_flag(target->np, OF_OVERLAY))
	if (!of_node_check_flag(target->np, OF_OVERLAY))
		pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
		       target->np, new_prop->name);