Loading arch/x86/kernel/process.c +55 −0 Original line number Diff line number Diff line Loading @@ -506,3 +506,58 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) return randomize_range(mm->brk, range_end, 0) ? : mm->brk; } /* * Called from fs/proc with a reference on @p to find the function * which called into schedule(). This needs to be done carefully * because the task might wake up and we might look at a stack * changing under us. */ unsigned long get_wchan(struct task_struct *p) { unsigned long start, bottom, top, sp, fp, ip; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; start = (unsigned long)task_stack_page(p); if (!start) return 0; /* * Layout of the stack page: * * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long) * PADDING * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING * stack * ----------- bottom = start + sizeof(thread_info) * thread_info * ----------- start * * The tasks stack pointer points at the location where the * framepointer is stored. The data on the stack is: * ... IP FP ... IP FP * * We need to read FP and IP, so we need to adjust the upper * bound by another unsigned long. */ top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING; top -= 2 * sizeof(unsigned long); bottom = start + sizeof(struct thread_info); sp = READ_ONCE(p->thread.sp); if (sp < bottom || sp > top) return 0; fp = READ_ONCE(*(unsigned long *)sp); do { if (fp < bottom || fp > top) return 0; ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long))); if (!in_sched_functions(ip)) return ip; fp = READ_ONCE(*(unsigned long *)fp); } while (count++ < 16 && p->state != TASK_RUNNING); return 0; } arch/x86/kernel/process_32.c +0 −28 Original line number Diff line number Diff line Loading @@ -324,31 +324,3 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) return prev_p; } #define top_esp (THREAD_SIZE - sizeof(unsigned long)) #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) unsigned long get_wchan(struct task_struct *p) { unsigned long bp, sp, ip; unsigned long stack_page; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; stack_page = (unsigned long)task_stack_page(p); sp = p->thread.sp; if (!stack_page || sp < stack_page || sp > top_esp+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes bp last. */ bp = *(unsigned long *) sp; do { if (bp < stack_page || bp > top_ebp+stack_page) return 0; ip = *(unsigned long *) (bp+4); if (!in_sched_functions(ip)) return ip; bp = *(unsigned long *) bp; } while (count++ < 16); return 0; } arch/x86/kernel/process_64.c +0 −24 Original line number Diff line number Diff line Loading @@ -499,30 +499,6 @@ void set_personality_ia32(bool x32) } EXPORT_SYMBOL_GPL(set_personality_ia32); unsigned long get_wchan(struct task_struct *p) { unsigned long stack; u64 fp, ip; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || fp >= (unsigned long)stack+THREAD_SIZE) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) return ip; fp = *(u64 *)fp; } while (count++ < 16); return 0; } long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { int ret = 0; Loading Loading
arch/x86/kernel/process.c +55 −0 Original line number Diff line number Diff line Loading @@ -506,3 +506,58 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) return randomize_range(mm->brk, range_end, 0) ? : mm->brk; } /* * Called from fs/proc with a reference on @p to find the function * which called into schedule(). This needs to be done carefully * because the task might wake up and we might look at a stack * changing under us. */ unsigned long get_wchan(struct task_struct *p) { unsigned long start, bottom, top, sp, fp, ip; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; start = (unsigned long)task_stack_page(p); if (!start) return 0; /* * Layout of the stack page: * * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long) * PADDING * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING * stack * ----------- bottom = start + sizeof(thread_info) * thread_info * ----------- start * * The tasks stack pointer points at the location where the * framepointer is stored. The data on the stack is: * ... IP FP ... IP FP * * We need to read FP and IP, so we need to adjust the upper * bound by another unsigned long. */ top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING; top -= 2 * sizeof(unsigned long); bottom = start + sizeof(struct thread_info); sp = READ_ONCE(p->thread.sp); if (sp < bottom || sp > top) return 0; fp = READ_ONCE(*(unsigned long *)sp); do { if (fp < bottom || fp > top) return 0; ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long))); if (!in_sched_functions(ip)) return ip; fp = READ_ONCE(*(unsigned long *)fp); } while (count++ < 16 && p->state != TASK_RUNNING); return 0; }
arch/x86/kernel/process_32.c +0 −28 Original line number Diff line number Diff line Loading @@ -324,31 +324,3 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) return prev_p; } #define top_esp (THREAD_SIZE - sizeof(unsigned long)) #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) unsigned long get_wchan(struct task_struct *p) { unsigned long bp, sp, ip; unsigned long stack_page; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; stack_page = (unsigned long)task_stack_page(p); sp = p->thread.sp; if (!stack_page || sp < stack_page || sp > top_esp+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes bp last. */ bp = *(unsigned long *) sp; do { if (bp < stack_page || bp > top_ebp+stack_page) return 0; ip = *(unsigned long *) (bp+4); if (!in_sched_functions(ip)) return ip; bp = *(unsigned long *) bp; } while (count++ < 16); return 0; }
arch/x86/kernel/process_64.c +0 −24 Original line number Diff line number Diff line Loading @@ -499,30 +499,6 @@ void set_personality_ia32(bool x32) } EXPORT_SYMBOL_GPL(set_personality_ia32); unsigned long get_wchan(struct task_struct *p) { unsigned long stack; u64 fp, ip; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || fp >= (unsigned long)stack+THREAD_SIZE) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) return ip; fp = *(u64 *)fp; } while (count++ < 16); return 0; } long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { int ret = 0; Loading