arm64: stacktrace: Relax frame record alignment requirement to 8 bytes
authorPeter Collingbourne <pcc@google.com>
Wed, 26 May 2021 17:49:26 +0000 (10:49 -0700)
committerWill Deacon <will@kernel.org>
Wed, 26 May 2021 19:01:17 +0000 (20:01 +0100)
The AAPCS places no requirements on the alignment of the frame
record. In theory it could be placed anywhere, although it seems
sensible to require it to be aligned to 8 bytes. With an upcoming
enhancement to tag-based KASAN Clang will begin creating frame records
located at an address that is only aligned to 8 bytes. Accommodate
such frame records in the stack unwinding code.

As pointed out by Mark Rutland, the userspace stack unwinding code
has the same problem, so fix it there as well.

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ia22c375230e67ca055e9e4bb639383567f7ad268
Acked-by: Andrey Konovalov <andreyknvl@gmail.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/r/20210526174927.2477847-2-pcc@google.com
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/perf_callchain.c
arch/arm64/kernel/stacktrace.c

index 88ff471b0bce5f2c49cb49cd38a3603fc952b2aa..4a72c2727309785bb599572da0cf3a511e10e227 100644 (file)
@@ -116,7 +116,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
                tail = (struct frame_tail __user *)regs->regs[29];
 
                while (entry->nr < entry->max_stack &&
-                      tail && !((unsigned long)tail & 0xf))
+                      tail && !((unsigned long)tail & 0x7))
                        tail = user_backtrace(tail, entry);
        } else {
 #ifdef CONFIG_COMPAT
index 5c70f247645bf45d12a5d5fec0bb0ad4d01f44e3..b189de5ca6cbc3dcdcc5c6020e585f1cc86c6f98 100644 (file)
@@ -75,7 +75,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
        if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
                return -ENOENT;
 
-       if (fp & 0xf)
+       if (fp & 0x7)
                return -EINVAL;
 
        if (!on_accessible_stack(tsk, fp, 16, &info))