]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: update getufpstack implementation to be safer
authorKris Van Hees <kris.van.hees@oracle.com>
Thu, 10 Oct 2013 20:17:13 +0000 (16:17 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Thu, 10 Oct 2013 20:33:31 +0000 (16:33 -0400)
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 <kris.van.hees@oracle.com>
dtrace/dtrace_isa.c

index 732d652e8539e282d1175aa9920e8668e03a81ab..428db59a2d94ab1f5c84fb0bf1e0ec5dac9dc298 100644 (file)
@@ -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)
 {