diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2023-07-28 10:50:28 +0200 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2023-08-23 20:04:17 -0500 |
commit | a9515ff4fb142b690a0d2b58782b15903b990dba (patch) | |
tree | 0ddb4c828070cdf5334a7106a0557235f19aaa41 /drivers/of/overlay.c | |
parent | 500d45100aa8546a000eef85bba8c2abc7b36e92 (diff) |
of: overlay: Call of_changeset_init() early
When of_overlay_fdt_apply() fails, the changeset may be partially
applied, and the caller is still expected to call of_overlay_remove() to
clean up this partial state.
However, of_overlay_apply() calls of_resolve_phandles() before
init_overlay_changeset(). Hence if the overlay fails to apply due to an
unresolved symbol, the overlay_changeset.cset.entries list is still
uninitialized, and cleanup will crash with a NULL-pointer dereference in
overlay_removal_is_ok().
Fix this by moving the call to of_changeset_init() from
init_overlay_changeset() to of_overlay_fdt_apply(), where all other
early initialization is done.
Fixes: f948d6d8b792bb90 ("of: overlay: avoid race condition between applying multiple overlays")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/4f1d6d74b61cba2599026adb6d1948ae559ce91f.1690533838.git.geert+renesas@glider.be
Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/of/overlay.c')
-rw-r--r-- | drivers/of/overlay.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 6f3ae30c878d..dfb6fb962fc7 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -769,8 +769,6 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, if (!of_node_is_root(ovcs->overlay_root)) pr_debug("%s() ovcs->overlay_root is not root\n", __func__); - of_changeset_init(&ovcs->cset); - cnt = 0; /* fragment nodes */ @@ -1033,6 +1031,7 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, INIT_LIST_HEAD(&ovcs->ovcs_list); list_add_tail(&ovcs->ovcs_list, &ovcs_list); + of_changeset_init(&ovcs->cset); /* * Must create permanent copy of FDT because of_fdt_unflatten_tree() |