summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-06-12 16:58:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-06-12 16:58:05 -0700
commit2ccbdf43d5e758f8493a95252073cf9078a5fea5 (patch)
treea6e13b68fce7b82e6e2bc09189d29c51bfb17c5a /arch
parent0b4989ebe8a608c68d5ec54d61078aba47baed22 (diff)
parent594ce0b8a998aa4d05827cd7c0d0dcec9a1e3ae2 (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM and clkdev fixes from Russell King: - Fix clkdev - erroring out on long strings causes boot failures, so don't do this. Still warn about the over-sized strings (which will never match and thus their registration with clkdev is useless) - Fix for ftrace with frame pointer unwinder with recent GCC changing the way frames are stacked. * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux: ARM: 9405/1: ftrace: Don't assume stack frames are contiguous in memory clkdev: don't fail clkdev_alloc() if over-sized
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/ftrace.c17
1 files changed, 15 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,