From: Nick Alcock Date: Fri, 29 Jan 2016 14:53:46 +0000 (+0000) Subject: dtrace: use copy_from_user() when walking userspace stacks X-Git-Tag: v4.1.12-111.0.20170907_2225~3^2~3^2~51 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=591cd72719494bc6db4c7522ad4d2ea7f079b247;p=users%2Fjedix%2Flinux-maple.git dtrace: use copy_from_user() when walking userspace stacks 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 Acked-by: Kris Van Hees --- diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index ae5d5c09082a8..a9e79b0fa8af7 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -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;