# Base git commit: 1613e604df0c
# (Linux 6.10-rc1)
# 
# Author:    Russell King (Oracle) (Mon 10 Jun 12:03:21 BST 2024)
# Committer: Russell King (Oracle) (Mon 10 Jun 12:03:21 BST 2024)
# 
#   Merge topic branches 'clkdev' and 'fixes' into for-linus
# 
# Author:    Ard Biesheuvel (Tue  4 Jun 22:32:34 BST 2024)
# Committer: Russell King (Oracle) (Mon 10 Jun 12:00:27 BST 2024)
# 
#   ARM: 9405/1: ftrace: Don't assume stack frames are contiguous in memory
# 
#   The frame pointer unwinder relies on a standard layout of the stack
#   frame, consisting of (in downward order)
# 
#      Calling frame:
#        PC   <---------+
#        LR             |
#        SP             |
#        FP             |
#        .. locals ..   |
#      Callee frame:    |
#        PC             |
#        LR             |
#        SP             |
#        FP   ----------+
# 
#   where after storing its previous value on the stack, FP is made to point
#   at the location of PC in the callee stack frame, using the canonical
#   prologue:
# 
#      mov     ip, sp
#      stmdb   sp!, {fp, ip, lr, pc}
#      sub     fp, ip, #4
# 
#   The ftrace code assumes that this activation record is pushed first, and
#   that any stack space for locals is allocated below this. Strict
#   adherence to this would imply that the caller's value of SP at the time
#   of the function call can always be obtained by adding 4 to FP (which
#   points to PC in the callee frame).
# 
#   However, recent versions of GCC appear to deviate from this rule, and so
#   the only reliable way to obtain the caller's value of SP is to read it
#   from the activation record. Since this involves a read from memory
#   rather than simple arithmetic, we need to use the uaccess API here which
#   protects against inadvertent data aborts resulting from attempts to
#   dereference bogus FP values.
# 
#   The plain uaccess API is ftrace instrumented itself, so to avoid
#   unbounded recursion, use the __get_kernel_nofault() primitive directly.
# 
#   Closes: https://lore.kernel.org/all/alp44tukzo6mvcwl4ke4ehhmojrqnv6xfcdeuliybxfjfvgd3e@gpjvwj33cc76
# 
#   Closes: https://lore.kernel.org/all/d870c149-4363-43de-b0ea-7125dec5608e@broadcom.com/
# 
#   Reported-by: Uwe Kleine-König
#   Reported-by: Justin Chen
#   Tested-by: Thorsten Scherer
#   Reviewed-by: Linus Walleij
#   Signed-off-by: Ard Biesheuvel
#   Signed-off-by: Russell King (Oracle)
# 
#   e3cf20e5c68df604315ab30bdbe15dc8a5da556b
#    arch/arm/kernel/ftrace.c | 17 +++++++++++++++--
#    1 file changed, 15 insertions(+), 2 deletions(-)
# 
# Author:    Russell King (Oracle) (Mon 27 May 09:00:06 BST 2024)
# Committer: Russell King (Oracle) (Tue  4 Jun 17:12:01 BST 2024)
# 
#   clkdev: don't fail clkdev_alloc() if over-sized
# 
#   Don't fail clkdev_alloc() if the strings are over-sized. In this case,
#   the entry will not match during lookup, so its useless. However, since
#   code fails if we return NULL leading to boot failure, return a dummy
#   entry with the connection and device IDs set to "bad".
# 
#   Leave the warning so these problems can be found, and the useless
#   wasteful clkdev registrations removed.
# 
#   Reported-by: Ron Economos
#   Reported-by: Guenter Roeck
#   Fixes: 8d532528ff6a ("clkdev: report over-sized strings when creating clkdev entries")
#   Closes: https://lore.kernel.org/linux-clk/7eda7621-0dde-4153-89e4-172e4c095d01@roeck-us.net.
#   Link: https://lore.kernel.org/r/28114882-f8d7-21bf-4536-a186e8d7a22a@w6rz.net
#   Tested-by: Ron Economos
#   Signed-off-by: Russell King (Oracle)
# 
#   616501eccb58615f8f352a29239ea6c6fc5e6546
#    drivers/clk/clkdev.c | 11 +++++++++--
#    1 file changed, 9 insertions(+), 2 deletions(-)
# 
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index a0b6d1e3812f..e61591f33a6c 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -232,11 +232,24 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	unsigned long old;
 
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+err_out:
 		return;
 
 	if (IS_ENABLED(CONFIG_UNWINDER_FRAME_POINTER)) {
-		/* FP points one word below parent's top of stack */
-		frame_pointer += 4;
+		/*
+		 * Usually, the stack frames are contiguous in memory but cases
+		 * have been observed where the next stack frame does not live
+		 * at 'frame_pointer + 4' as this code used to assume.
+		 *
+		 * Instead, dereference the field in the stack frame that
+		 * stores the SP of the calling frame: to avoid unbounded
+		 * recursion, this cannot involve any ftrace instrumented
+		 * functions, so use the __get_kernel_nofault() primitive
+		 * directly.
+		 */
+		__get_kernel_nofault(&frame_pointer,
+				     (unsigned long *)(frame_pointer - 8),
+				     unsigned long, err_out);
 	} else {
 		struct stackframe frame = {
 			.fp = frame_pointer,
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 6a77d7e201a9..2f83fb97c6fb 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -204,8 +204,15 @@ vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
 	pr_err("%pV:%s: %s ID is greater than %zu\n",
 	       &vaf, con_id, failure, max_size);
 	va_end(ap_copy);
-	kfree(cla);
-	return NULL;
+
+	/*
+	 * Don't fail in this case, but as the entry won't ever match just
+	 * fill it with something that also won't match.
+	 */
+	strscpy(cla->con_id, "bad", sizeof(cla->con_id));
+	strscpy(cla->dev_id, "bad", sizeof(cla->dev_id));
+
+	return &cla->cl;
 }
 
 static struct clk_lookup *
