| From e914535cc137a9f4547d97e51a6a5cc755d9c676 Mon Sep 17 00:00:00 2001 |
| From: Geert Uytterhoeven <geert+renesas@glider.be> |
| 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 |
| identical. |
| |
| 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 <geert+renesas@glider.be> |
| Reviewed-by: Frank Rowand <frank.rowand@sony.com> |
| Signed-off-by: Rob Herring <robh@kernel.org> |
| (cherry picked from commit 5e4748175fe942c86cbab840e2fa41a92b4d6cf6) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| 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) |
| } |
| |
| of_overlay_mutex_lock(); |
| + 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; |
| - |
| -err_overlay_unlock: |
| - of_overlay_mutex_unlock(); |
| + goto out_unlock; |
| |
| err_free_overlay_changeset: |
| free_overlay_changeset(ovcs); |
| |
| +out_unlock: |
| mutex_unlock(&of_mutex); |
| + of_overlay_mutex_unlock(); |
| |
| out: |
| pr_debug("%s() err=%d\n", __func__, ret); |
| -- |
| 2.19.0 |
| |