From: Kris Van Hees Date: Thu, 10 Oct 2013 20:17:13 +0000 (-0400) Subject: dtrace: update getufpstack implementation to be safer X-Git-Tag: v4.1.12-111.0.20170907_2225~3^2~3^2~118 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=00bf80af37248521fb6f24165dd2290bdc34e878;p=users%2Fjedix%2Flinux-maple.git dtrace: update getufpstack implementation to be safer The dtrace_getufpstack() function was a death trap when called for cases where current happened to be in a transitional state (no mm) or a kthread. It was also using find_vma() when that was not quite necessary. Finally, it was not correctly using the saved stack pointer from userspace correctly (in one place it used old_rsp as appropriate, but in another p->thread.usersp). The code has been rewritten to make use of the fact that the only valid stack addresses that can be in use when this function is called must appear between the current stack pointer position (old_rsp) and the bottom of the stack (mm->start_stack). Therefore, no vma is necessary anymore. The new implementation also ensures that when there is no mm, or we're dealing with a kthread, the resulting data is still formatted correctly, i.e. with a PID in the first slot, and zeros in all other slots. This commit effectively builds on top of the fix applied by Nick Alcock. Orabug: 17591351 Signed-off-by: Kris Van Hees --- diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index 732d652e8539e..428db59a2d94a 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -283,26 +283,23 @@ void dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) { struct task_struct *p = current; - unsigned long *sp = (unsigned long *)this_cpu_read(old_rsp); - unsigned long *bos; - struct vm_area_struct *stack_vma; - - if ((p->mm == NULL) || (p->flags & PF_KTHREAD)) - return; - - bos = (unsigned long *)p->mm->start_stack; - stack_vma = find_vma(p->mm, p->thread.usersp); - - if (stack_vma == NULL) - return; + unsigned long bos, tos; + unsigned long *sp; *pcstack++ = (uint64_t)p->pid; pcstack_limit--; - while (sp <= bos && pcstack_limit) { + if (p->mm == NULL || (p->flags & PF_KTHREAD)) + goto out; + + tos = this_cpu_read(old_rsp); + bos = p->mm->start_stack; + + for (sp = (unsigned long *)tos; + sp <= (unsigned long *)bos && pcstack_limit; sp++) { unsigned long addr = *sp; - if (addr >= stack_vma->vm_start && addr < stack_vma->vm_end) { + if (addr >= tos && addr <= bos) { /* stack address - may need it for the fpstack. */ } else if (is_code_addr(addr)) { *pcstack++ = addr; @@ -312,11 +309,10 @@ void dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, sp++; } +out: while (pcstack_limit--) *pcstack++ = 0; - - ASSERT(current == p); -} +} void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) {