diff mbox series

[V6,3/4] lib: hashtable: Prevent recursive calling of callback functions

Message ID 20241206230420.54704-4-cniedermaier@dh-electronics.com
State Accepted
Commit 86f58ea539e35b47235dff0dd77ec20fe8894469
Delegated to: Fabio Estevam
Headers show
Series arm64: imx8mp: Read values from M24C32-D write-lockable page on DHCOM i.MX8MP | expand

Commit Message

Christoph Niedermaier Dec. 6, 2024, 11:04 p.m. UTC
In case there are two variables which each implement env callback
that performs env_set() on the other variable, the callbacks will
call each other recursively until the stack runs out. Prevent such
a recursion from happening.

Example which triggers this behavior:
static int on_foo(...) { env_set("bar", 0); ... }
static int on_bar(...) { env_set("foo", 0); ... }
U_BOOT_ENV_CALLBACK(foo, on_foo);
U_BOOT_ENV_CALLBACK(bar, on_bar);

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
Suggested-by: Marek Vasut <marex@denx.de>
---
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Marek Vasut <marex@denx.de>
Cc: u-boot@dh-electronics.com
---
V4: - Add this patch to the series
v5: - No functional changes, but changed the order of the patches
V6: - No changes
---
 lib/hashtable.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/lib/hashtable.c b/lib/hashtable.c
index e8a59e2dca..75c263b505 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -221,11 +221,32 @@  static int
 do_callback(const struct env_entry *e, const char *name, const char *value,
 	    enum env_op op, int flags)
 {
+	int ret = 0;
+
 #ifndef CONFIG_XPL_BUILD
-	if (e->callback)
-		return e->callback(name, value, op, flags);
+	static bool in_callback;
+
+	if (!e->callback || in_callback)
+		return 0;
+
+	/*
+	 * In case there are two variables which each implement env callback
+	 * that performs env_set() on the other variable, the callbacks will
+	 * call each other recursively until the stack runs out. Prevent such
+	 * a recursion from happening.
+	 *
+	 * Example which triggers this behavior:
+	 * static int on_foo(...) { env_set("bar", 0); ... }
+	 * static int on_bar(...) { env_set("foo", 0); ... }
+	 * U_BOOT_ENV_CALLBACK(foo, on_foo);
+	 * U_BOOT_ENV_CALLBACK(bar, on_bar);
+	 */
+	in_callback = true;
+	ret = e->callback(name, value, op, flags);
+	in_callback = false;
 #endif
-	return 0;
+
+	return ret;
 }
 
 /*