Skip to content

Commit bc9bbb8

Browse files
Qi ZhengPeter Zijlstra
Qi Zheng
authored and
Peter Zijlstra
committed
x86: Fix get_wchan() to support the ORC unwinder
Currently, the kernel CONFIG_UNWINDER_ORC option is enabled by default on x86, but the implementation of get_wchan() is still based on the frame pointer unwinder, so the /proc/<pid>/wchan usually returned 0 regardless of whether the task <pid> is running. Reimplement get_wchan() by calling stack_trace_save_tsk(), which is adapted to the ORC and frame pointer unwinders. Fixes: ee9f8fc ("x86/unwind: Add the ORC unwinder") Signed-off-by: Qi Zheng <[email protected]> Signed-off-by: Kees Cook <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 4e04615 commit bc9bbb8

File tree

1 file changed

+3
-48
lines changed

1 file changed

+3
-48
lines changed

arch/x86/kernel/process.c

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -944,58 +944,13 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
944944
*/
945945
unsigned long get_wchan(struct task_struct *p)
946946
{
947-
unsigned long start, bottom, top, sp, fp, ip, ret = 0;
948-
int count = 0;
947+
unsigned long entry = 0;
949948

950949
if (p == current || task_is_running(p))
951950
return 0;
952951

953-
if (!try_get_task_stack(p))
954-
return 0;
955-
956-
start = (unsigned long)task_stack_page(p);
957-
if (!start)
958-
goto out;
959-
960-
/*
961-
* Layout of the stack page:
962-
*
963-
* ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long)
964-
* PADDING
965-
* ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING
966-
* stack
967-
* ----------- bottom = start
968-
*
969-
* The tasks stack pointer points at the location where the
970-
* framepointer is stored. The data on the stack is:
971-
* ... IP FP ... IP FP
972-
*
973-
* We need to read FP and IP, so we need to adjust the upper
974-
* bound by another unsigned long.
975-
*/
976-
top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;
977-
top -= 2 * sizeof(unsigned long);
978-
bottom = start;
979-
980-
sp = READ_ONCE(p->thread.sp);
981-
if (sp < bottom || sp > top)
982-
goto out;
983-
984-
fp = READ_ONCE_NOCHECK(((struct inactive_task_frame *)sp)->bp);
985-
do {
986-
if (fp < bottom || fp > top)
987-
goto out;
988-
ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
989-
if (!in_sched_functions(ip)) {
990-
ret = ip;
991-
goto out;
992-
}
993-
fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
994-
} while (count++ < 16 && !task_is_running(p));
995-
996-
out:
997-
put_task_stack(p);
998-
return ret;
952+
stack_trace_save_tsk(p, &entry, 1, 0);
953+
return entry;
999954
}
1000955

1001956
long do_arch_prctl_common(struct task_struct *task, int option,

0 commit comments

Comments
 (0)