]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: use copy_from_user() when walking userspace stacks
authorNick Alcock <nick.alcock@oracle.com>
Fri, 29 Jan 2016 14:53:46 +0000 (14:53 +0000)
committerNick Alcock <nick.alcock@oracle.com>
Wed, 3 Feb 2016 16:36:59 +0000 (16:36 +0000)
We were using get_user(), but that doesn't reliably work on all
platforms (such as SPARC64) and cannot trap faults, which meant we were
jumping through extra hoops to trap faults when copy_from_user() does
that anyway.

The extra copy is notably less efficient (since we end up looping over,
and copying, essentially the entire user stack in one-word increments),
but has the advantage of actually working.

Orabug: 22629102
Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Acked-by: Kris Van Hees <kris.van.hees@oracle.com>
dtrace/dtrace_isa.c

index ae5d5c09082a8c5fd248483c7e0b6f011f1d8cf5..a9e79b0fa8af723ffdf80b989f8806b71baf9d95 100644 (file)
@@ -263,6 +263,7 @@ unsigned long dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack,
             sp++) {
                struct vm_area_struct   *code_vma;
                unsigned long           addr;
+               int                     copyret;
 
                /*
                 * Recheck for faultedness and pin at page boundaries.
@@ -278,14 +279,11 @@ unsigned long dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack,
                                break;
                }
 
-               DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-               get_user(addr, sp);
-               DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-
-               if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) {
-                       DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_BADADDR);
+               pagefault_disable();
+               copyret = copy_from_user(&addr, sp, sizeof(addr));
+               pagefault_enable();
+               if (copyret)
                        break;
-               }
 
                if (addr == fpc)
                        continue;