blob: 452b942d18f0ffb5852f572e8e4cbdd9a99fd290 [file] [log] [blame]
From e914535cc137a9f4547d97e51a6a5cc755d9c676 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <>
Date: Tue, 5 Dec 2017 16:27:03 +0100
Subject: [PATCH 0922/1795] of: overlay: Fix (un)locking in of_overlay_apply()
The special overlay mutex is taken first, hence it should be released
last in the error path.
of_resolve_phandles() must be called with of_mutex held. Without it, a
node and new phandle could be added via of_attach_node(), making the max
phandle wrong.
free_overlay_changeset() must be called with of_mutex held, if any
non-trivial cleanup is to be done.
Hence move "mutex_lock(&of_mutex)" up, as suggested by Frank, and merge
the two tail statements of the success and error paths, now they became
Note that while the two mutexes are adjacent, we still need both:
__of_changeset_apply_notify(), which is called by __of_changeset_apply()
unlocks of_mutex, then does notifications then locks of_mutex. So the
mutex get released in the middle of of_overlay_apply()
Fixes: f948d6d8b792bb90 ("of: overlay: avoid race condition between applying multiple overlays")
Signed-off-by: Geert Uytterhoeven <>
Reviewed-by: Frank Rowand <>
Signed-off-by: Rob Herring <>
(cherry picked from commit 5e4748175fe942c86cbab840e2fa41a92b4d6cf6)
Signed-off-by: Simon Horman <>
Signed-off-by: Geert Uytterhoeven <>
drivers/of/overlay.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index bb3f123ed259..fcce5cdbe229 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -706,12 +706,11 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
+ mutex_lock(&of_mutex);
ret = of_resolve_phandles(tree);
if (ret)
- goto err_overlay_unlock;
- mutex_lock(&of_mutex);
+ goto err_free_overlay_changeset;
ret = init_overlay_changeset(ovcs, tree);
if (ret)
@@ -754,18 +753,14 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
ret = ret_tmp;
- mutex_unlock(&of_mutex);
- of_overlay_mutex_unlock();
- goto out;
- of_overlay_mutex_unlock();
+ goto out_unlock;
+ of_overlay_mutex_unlock();
pr_debug("%s() err=%d\n", __func__, ret);