Use the compiler-provided frame pointer when CONFIG_FRAME_POINTER is enabled to restrict the stack canary search range to the current function frame. This prevents scanning beyond valid stack bounds and improves reliability across architectures.
Also add explicit handling for missing CONFIG_STACKPROTECTOR and make the failure message more visible. Signed-off-by: Jinchao Wang <[email protected]> --- mm/kstackwatch/stack.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/mm/kstackwatch/stack.c b/mm/kstackwatch/stack.c index 60371b292915..3455d1e70db9 100644 --- a/mm/kstackwatch/stack.c +++ b/mm/kstackwatch/stack.c @@ -64,15 +64,32 @@ static unsigned long ksw_find_stack_canary_addr(struct pt_regs *regs) unsigned long *stack_ptr, *stack_end, *stack_base; unsigned long expected_canary; unsigned int i; +#ifdef CONFIG_FRAME_POINTER + unsigned long *fp = NULL; +#endif stack_ptr = (unsigned long *)kernel_stack_pointer(regs); - stack_base = (unsigned long *)(current->stack); - // TODO: limit it to the current frame stack_end = (unsigned long *)((char *)current->stack + THREAD_SIZE); +#ifdef CONFIG_FRAME_POINTER + /* + * Use the compiler-provided frame pointer. + * Limit the search to the current frame + * Works on any arch that keeps FP when CONFIG_FRAME_POINTER=y. + */ + fp = __builtin_frame_address(0); + if (fp > stack_ptr && fp < stack_end) + stack_end = fp; +#endif + +#ifdef CONFIG_STACKPROTECTOR expected_canary = current->stack_canary; +#else + pr_err("no canary without CONFIG_STACKPROTECTOR\n"); + return 0; +#endif if (stack_ptr < stack_base || stack_ptr >= stack_end) { pr_err("Stack pointer 0x%lx out of bounds [0x%lx, 0x%lx)\n", @@ -85,15 +102,11 @@ static unsigned long ksw_find_stack_canary_addr(struct pt_regs *regs) if (&stack_ptr[i] >= stack_end) break; - if (stack_ptr[i] == expected_canary) { - pr_debug("canary found i:%d 0x%lx\n", i, - (unsigned long)&stack_ptr[i]); + if (stack_ptr[i] == expected_canary) return (unsigned long)&stack_ptr[i]; - } } - pr_debug("canary not found in first %d steps\n", - MAX_CANARY_SEARCH_STEPS); + pr_err("canary not found in first %d steps\n", MAX_CANARY_SEARCH_STEPS); return 0; } -- 2.43.0
