From: frowand.list@gmail.com
To: Rob Herring <robh+dt@kernel.org>,
Pantelis Antoniou <pantelis.antoniou@konsulko.com>,
David Airlie <airlied@linux.ie>, Jyri Sarha <jsarha@ti.com>
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Mark Rutland <mark.rutland@arm.com>,
Tomi Valkeinen <tomi.valkeinen@ti.com>,
dri-devel@lists.freedesktop.org
Subject: [PATCH 09/12] of: overlay: avoid race condition between applying multiple overlays
Date: Mon, 2 Oct 2017 20:53:43 -0700 [thread overview]
Message-ID: <1507002826-16393-10-git-send-email-frowand.list@gmail.com> (raw)
In-Reply-To: <1507002826-16393-1-git-send-email-frowand.list@gmail.com>
From: Frank Rowand <frank.rowand@sony.com>
The process of applying an overlay consists of:
- unflatten an overlay FDT (flattened device tree) into an
EDT (expanded device tree)
- fixup the phandle values in the overlay EDT to fit in a
range above the phandle values in the live device tree
- create the overlay changeset to reflect the contents of
the overlay EDT
- apply the overlay changeset, to modify the live device tree,
potentially changing the maximum phandle value in the live
device tree
There is currently no protection against two overlay applies
concurrently determining what range of phandle values are in use
in the live device tree, and subsequently changing that range.
Add a mutex to prevent multiple overlay applies from occurring
simultaneously.
Ignoring 2 checkpatch warnings: Prefer using '"%s...", __func__'
so that the WARN() string will be more easily grepped.
Signed-off-by: Frank Rowand <frank.rowand@sony.com>
---
drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 7 +++++++
drivers/of/overlay.c | 22 ++++++++++++++++++++++
drivers/of/unittest.c | 21 +++++++++++++++++++++
include/linux/of.h | 19 +++++++++++++++++++
4 files changed, 69 insertions(+)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c
index 7a7be0515bfd..c99f7924b1c6 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c
@@ -221,6 +221,11 @@ static void __init tilcdc_convert_slave_node(void)
goto out;
}
+ /*
+ * protect from of_resolve_phandles() through of_overlay_apply()
+ */
+ of_overlay_mutex_lock();
+
overlay = tilcdc_get_overlay(&kft);
if (!overlay)
goto out;
@@ -256,6 +261,8 @@ static void __init tilcdc_convert_slave_node(void)
pr_info("%s: ti,tilcdc,slave node successfully converted\n",
__func__);
out:
+ of_overlay_mutex_unlock();
+
kfree_table_free(&kft);
of_node_put(i2c);
of_node_put(slave);
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index a0d3222febdc..4ed372af6ce7 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -71,6 +71,28 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs,
const struct device_node *overlay_node,
bool is_symbols_node);
+/*
+ * of_resolve_phandles() finds the largest phandle in the live tree.
+ * of_overlay_apply() may add a larger phandle to the live tree.
+ * Do not allow race between two overlays being applied simultaneously:
+ * mutex_lock(&of_overlay_phandle_mutex)
+ * of_resolve_phandles()
+ * of_overlay_apply()
+ * mutex_unlock(&of_overlay_phandle_mutex)
+ */
+static DEFINE_MUTEX(of_overlay_phandle_mutex);
+
+void of_overlay_mutex_lock(void)
+{
+ mutex_lock(&of_overlay_phandle_mutex);
+}
+
+void of_overlay_mutex_unlock(void)
+{
+ mutex_unlock(&of_overlay_phandle_mutex);
+}
+
+
static LIST_HEAD(ovcs_list);
static DEFINE_IDR(ovcs_idr);
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index db2f170186de..f4c8aff21320 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -994,9 +994,17 @@ static int __init unittest_data_add(void)
return -ENODATA;
}
of_node_set_flag(unittest_data_node, OF_DETACHED);
+
+ /*
+ * This lock normally encloses of_overlay_apply() as well as
+ * of_resolve_phandles().
+ */
+ of_overlay_mutex_lock();
+
rc = of_resolve_phandles(unittest_data_node);
if (rc) {
pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc);
+ of_overlay_mutex_unlock();
return -EINVAL;
}
@@ -1006,6 +1014,7 @@ static int __init unittest_data_add(void)
__of_attach_node_sysfs(np);
of_aliases = of_find_node_by_path("/aliases");
of_chosen = of_find_node_by_path("/chosen");
+ of_overlay_mutex_unlock();
return 0;
}
@@ -1018,6 +1027,9 @@ static int __init unittest_data_add(void)
attach_node_and_children(np);
np = next;
}
+
+ of_overlay_mutex_unlock();
+
return 0;
}
@@ -2150,9 +2162,12 @@ static int __init overlay_data_add(int onum)
}
of_node_set_flag(info->np_overlay, OF_DETACHED);
+ of_overlay_mutex_lock();
+
ret = of_resolve_phandles(info->np_overlay);
if (ret) {
pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum);
+ of_overlay_mutex_unlock();
goto out_free_np_overlay;
}
@@ -2160,9 +2175,12 @@ static int __init overlay_data_add(int onum)
ret = of_overlay_apply(info->np_overlay, &info->overlay_id);
if (ret < 0) {
pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum);
+ of_overlay_mutex_unlock();
goto out_free_np_overlay;
}
+ of_overlay_mutex_unlock();
+
pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret);
goto out;
@@ -2209,7 +2227,10 @@ static __init void of_unittest_overlay_high_level(void)
* Could not fixup phandles in unittest_unflatten_overlay_base()
* because kmalloc() was not yet available.
*/
+ of_overlay_mutex_lock();
of_resolve_phandles(overlay_base_root);
+ of_overlay_mutex_unlock();
+
/*
* do not allow overlay_base to duplicate any node already in
diff --git a/include/linux/of.h b/include/linux/of.h
index 49e5f24fb390..eb60eddf83c2 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1306,6 +1306,9 @@ struct of_overlay_notify_data {
#ifdef CONFIG_OF_OVERLAY
/* ID based overlays; the API for external users */
+void of_overlay_mutex_lock(void);
+void of_overlay_mutex_unlock(void);
+
int of_overlay_apply(struct device_node *tree, int *ovcs_id);
int of_overlay_remove(int *ovcs_id);
int of_overlay_remove_all(void);
@@ -1315,6 +1318,22 @@ struct of_overlay_notify_data {
#else
+static inline void of_overlay_mutex_lock(void)
+{
+#ifndef CONFIG_OF_RESOLVE
+ /* avoid warning in unittest.c */
+ WARN(1, "of_overlay_mutex_lock() ifdef'ed out\n");
+#endif
+}
+
+static inline void of_overlay_mutex_unlock(void)
+{
+#ifndef CONFIG_OF_RESOLVE
+ /* avoid warning in unittest.c */
+ WARN(1, "of_overlay_mutex_unlock() ifdef'ed out\n");
+#endif
+}
+
static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id)
{
return -ENOTSUPP;
--
Frank Rowand <frank.rowand@sony.com>
next prev parent reply other threads:[~2017-10-03 3:53 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-03 3:53 [PATCH 00/12] of: overlay: clean up device tree overlay code frowand.list-Re5JQEeQqe8AvxtiuMwx3w
2017-10-03 3:53 ` [PATCH 01/12] of: overlay.c: Remove comments that state the obvious, to reduce clutter frowand.list
2017-10-03 3:53 ` [PATCH 02/12] of: overlay.c: Convert comparisons to zero or NULL to logical expressions frowand.list
2017-10-03 3:53 ` [PATCH 04/12] of: overlay: rename identifiers in dup_and_fixup_symbol_prop() frowand.list
2017-10-03 3:53 ` [PATCH 05/12] of: overlay: minor restructuring frowand.list
2017-10-03 3:53 ` [PATCH 06/12] of: overlay: detect cases where device tree may become corrupt frowand.list
2017-10-03 3:53 ` [PATCH 08/12] of: overlay: loosen overly strict phandle clash check frowand.list
2017-10-03 3:53 ` frowand.list [this message]
2017-10-04 15:19 ` [PATCH 09/12] of: overlay: avoid race condition between applying multiple overlays Rob Herring
2017-10-05 3:29 ` Frank Rowand
2017-10-10 18:40 ` Rob Herring
2017-10-10 19:39 ` Frank Rowand
2017-10-10 21:06 ` Rob Herring
2017-10-11 0:53 ` Frank Rowand
[not found] ` <CAL_JsqK8cxBk754UBziGOTMx035C8P5ehPvENE0=-TNHqmTCbg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-10-11 1:41 ` Frank Rowand
[not found] ` <1507002826-16393-1-git-send-email-frowand.list-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-10-03 3:53 ` [PATCH 03/12] of: overlay: rename identifiers to more reflect what they do frowand.list-Re5JQEeQqe8AvxtiuMwx3w
2017-10-03 3:53 ` [PATCH 07/12] of: overlay: expand check of whether overlay changeset can be removed frowand.list-Re5JQEeQqe8AvxtiuMwx3w
2017-10-03 3:53 ` [PATCH 10/12] of: overlay: simplify applying symbols from an overlay frowand.list-Re5JQEeQqe8AvxtiuMwx3w
2017-10-04 14:56 ` [PATCH 00/12] of: overlay: clean up device tree overlay code Rob Herring
2017-10-05 6:53 ` Tomi Valkeinen
[not found] ` <3eac16b0-fdd9-fd6c-e1ca-e0de49ce27cb-l0cyMroinI0@public.gmane.org>
2017-10-05 8:33 ` Jyri Sarha
2017-10-17 8:43 ` Jyri Sarha
2017-10-05 14:46 ` Rob Herring
2017-10-03 3:53 ` [PATCH 11/12] of: overlay: remove a dependency on device node full_name frowand.list
2017-10-03 3:53 ` [PATCH 12/12] of: overlay: remove unneeded check for NULL kbasename() frowand.list
2017-10-13 22:03 ` [PATCH 00/12] of: overlay: clean up device tree overlay code Frank Rowand
2017-10-16 20:55 ` Rob Herring
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1507002826-16393-10-git-send-email-frowand.list@gmail.com \
--to=frowand.list@gmail.com \
--cc=airlied@linux.ie \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jsarha@ti.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=pantelis.antoniou@konsulko.com \
--cc=robh+dt@kernel.org \
--cc=tomi.valkeinen@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).