When we started work on W^X, we knew it would be a long road due to the prevalance of JIT tooling.
1) Some of the JIT tooling is clean and will flip memory between W and X states -- accepting the cost of mprotect(). 2) Other JIT tooling creates aliases between a pair of W and X mappings of the same memory (sadly, sometimes with pointers or deltas which I think are too discoverable) 3) Other JIT tooling is even dirtier, and requires the W|X memory model. The W^X picture has gotten better. There are more programs in catagories 1 and 2 now, and fewer in 3. But we wanted to run the W|X JIT programs, in particular chrome/iridium after pledge (and later unveil) was added to mitigate the system call (and filesystem view) problems. So partly admitting defeat, I created a "wxneeded" ELF marker, and a "wxallowed" filesystem mount option, so that the W|X binaries could be run from such a filesystem (/usr/local). Recently I considered the potential case of code-upload into the JIT W|X code arenas which might contain native system call instructions. I wish to block direct system calls from those areas, thereby forcing the attacker to deal with the (hopefully) more complex effort of using JIT support environment code, or probably even harder discovering the syscall stubs directly inside the randomly-relinked libc. Even if the JIT support access method is not more complicated, I want to remove the direct syscall exploitation avenue. With chrome/iridium on OpenBSD, the processes operating JIT are tightly pledged, but taking away the write(2) system call obviously has some advantage, as we steer the attacker towards using the JIT support code. This diff refactors the MAP_STACK pseudo-permission bit code, adding additional code which checks if a syscall is being performed from a writeable page. If the page is writeable, the process is killed. There is one concern. Are there any JIT which create native syscalls inside W|X memory? I am hopeful because we've changed the syscall ABI so often and never heard of failure modes. This diff is now in snapshots, to help my dear readers discover any potential problems. ps. In related news, chrome has a JIT-less mode in development which does no W|X mappings. It is acceptable for more minimal usage patterns, but obviously uses a lot more cpu. As well, chrome will now mostly work if you disable "wxallowed" on the filesystem. At startup it observes MAP_WRITE|MAP_EXEC fails with ENOTSUP, and then proceeds to use mprotect to flip pages between modes. It *mostly* works, there are problems with some plugins (ghostery, for instance), but I'm very hopeful they will complete this work in the near future. Index: sys/proc.h =================================================================== RCS file: /cvs/src/sys/sys/proc.h,v retrieving revision 1.265 diff -u -p -u -r1.265 proc.h --- sys/proc.h 13 May 2019 19:21:31 -0000 1.265 +++ sys/proc.h 27 May 2019 12:12:43 -0000 @@ -298,6 +298,12 @@ struct process { struct kcov_dev; struct lock_list_entry; +struct p_inentry { + u_int ie_serial; + vaddr_t ie_start; + vaddr_t ie_end; +}; + /* * Locks used to protect struct members in this file: * s scheduler lock @@ -315,6 +321,8 @@ struct proc { /* substructures: */ struct filedesc *p_fd; /* copy of p_p->ps_fd */ struct vmspace *p_vmspace; /* copy of p_p->ps_vmspace */ + struct p_inentry p_spinentry; + struct p_inentry p_pcinentry; #define p_rlimit p_p->ps_limit->pl_rlimit int p_flag; /* P_* flags. */ @@ -357,10 +365,6 @@ struct proc { /* The following fields are all copied upon creation in fork. */ #define p_startcopy p_sigmask sigset_t p_sigmask; /* Current signal mask. */ - - u_int p_spserial; - vaddr_t p_spstart; - vaddr_t p_spend; u_char p_priority; /* [s] Process priority. */ u_char p_usrpri; /* [s] User-prio based on p_estcpu & ps_nice. */ Index: sys/syscall_mi.h =================================================================== RCS file: /cvs/src/sys/sys/syscall_mi.h,v retrieving revision 1.19 diff -u -p -u -r1.19 syscall_mi.h --- sys/syscall_mi.h 12 Apr 2018 17:13:44 -0000 1.19 +++ sys/syscall_mi.h 27 May 2019 12:12:43 -0000 @@ -50,7 +50,6 @@ mi_syscall(struct proc *p, register_t co uint64_t tval; int lock = !(callp->sy_flags & SY_NOLOCK); int error, pledged; - vaddr_t sp = PROC_STACK(p); /* refresh the thread's cache of the process's creds */ refreshcreds(p); @@ -68,24 +67,16 @@ mi_syscall(struct proc *p, register_t co } #endif - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || sp >= p->p_spend) { - KERNEL_LOCK(); + /* SP must be within MAP_STACK space */ + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return (EPERM); + + /* PC must not be in writeable memory */ + if (!uvm_map_inentry(p, &p->p_pcinentry, PROC_PC(p), "pc", + uvm_map_inentry_pc, p->p_vmspace->vm_map.wserial)) + return (EPERM); - if (!uvm_map_check_stack_range(p, sp)) { - printf("syscall [%s]%d/%d sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - sp, p->p_spstart, p->p_spend); - - p->p_sitrapno = 0; - p->p_sicode = SEGV_ACCERR; - p->p_sigval.sival_ptr = (void *)PROC_PC(p); - psignal(p, SIGSEGV); - KERNEL_UNLOCK(); - return (EPERM); - } - KERNEL_UNLOCK(); - } if (lock) KERNEL_LOCK(); pledged = (p->p_p->ps_flags & PS_PLEDGE); Index: uvm/uvm_map.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_map.c,v retrieving revision 1.244 diff -u -p -u -r1.244 uvm_map.c --- uvm/uvm_map.c 16 May 2019 04:24:14 -0000 1.244 +++ uvm/uvm_map.c 27 May 2019 14:08:05 -0000 @@ -91,7 +91,9 @@ #include <sys/malloc.h> #include <sys/pool.h> #include <sys/sysctl.h> +#include <sys/signalvar.h> #include <sys/syslog.h> +#include <sys/user.h> #ifdef SYSVSHM #include <sys/shm.h> @@ -1071,6 +1073,8 @@ uvm_mapanon(struct vm_map *map, vaddr_t entry->inheritance = inherit; entry->wired_count = 0; entry->advice = advice; + if (prot & PROT_WRITE) + map->wserial++; if (flags & UVM_FLAG_STACK) { entry->etype |= UVM_ET_STACK; if (flags & (UVM_FLAG_FIXED | UVM_FLAG_UNMAP)) @@ -1334,6 +1338,8 @@ uvm_map(struct vm_map *map, vaddr_t *add entry->inheritance = inherit; entry->wired_count = 0; entry->advice = advice; + if (prot & PROT_WRITE) + map->wserial++; if (flags & UVM_FLAG_STACK) { entry->etype |= UVM_ET_STACK; if (flags & UVM_FLAG_UNMAP) @@ -1779,42 +1785,100 @@ uvm_map_lookup_entry(struct vm_map *map, } /* - * Inside a vm_map find the sp address and verify MAP_STACK, and also - * remember low and high regions of that of region which is marked - * with MAP_STACK. Return TRUE. - * If sp isn't in a non-guard MAP_STACK region return FALSE. + * Stack must be in a MAP_STACK entry. PROT_NONE indicates stack not yet + * grown -- then uvm_map_check_region_range() should not cache the entry + * because growth won't be seen. + */ +int +uvm_map_inentry_sp(vm_map_entry_t entry) +{ + if ((entry->etype & UVM_ET_STACK) == 0) { + if (entry->protection == PROT_NONE) + return (-1); /* don't update range */ + return (0); + } + return (1); +} + +/* + * If a syscall comes from a writeable entry, W^X is violated. + * (Would be nice if we can spot aliasing, which is also kind of bad) + */ +int +uvm_map_inentry_pc(vm_map_entry_t entry) +{ + if (entry->protection & PROT_WRITE) + return (0); /* not permitted */ + return (1); +} + +int +uvm_map_inentry_recheck(u_int serial, vaddr_t addr, struct p_inentry *ie) +{ + return (serial != ie->ie_serial || ie->ie_start == 0 || + addr < ie->ie_start || addr >= ie->ie_end); +} + +/* + * Inside a vm_map find the reg address and verify it via function. + * Remember low and high addresses of region if valid and return TRUE, + * else return FALSE. */ boolean_t -uvm_map_check_stack_range(struct proc *p, vaddr_t sp) +uvm_map_inentry_fix(struct proc *p, struct p_inentry *ie, vaddr_t addr, + int (*fn)(vm_map_entry_t), u_int serial) { vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; + int ret; - if (sp < map->min_offset || sp >= map->max_offset) - return(FALSE); + if (addr < map->min_offset || addr >= map->max_offset) + return (FALSE); /* lock map */ vm_map_lock_read(map); /* lookup */ - if (!uvm_map_lookup_entry(map, trunc_page(sp), &entry)) { + if (!uvm_map_lookup_entry(map, trunc_page(addr), &entry)) { vm_map_unlock_read(map); - return(FALSE); + return (FALSE); } - if ((entry->etype & UVM_ET_STACK) == 0) { - int protection = entry->protection; - + ret = (*fn)(entry); + if (ret == 0) { vm_map_unlock_read(map); - if (protection == PROT_NONE) - return (TRUE); /* don't update range */ return (FALSE); + } else if (ret == 1) { + ie->ie_start = entry->start; + ie->ie_end = entry->end; + ie->ie_serial = serial; + } else { + /* do not update, re-check later */ } - p->p_spstart = entry->start; - p->p_spend = entry->end; - p->p_spserial = map->serial; vm_map_unlock_read(map); - return(TRUE); + return (TRUE); +} + +boolean_t +uvm_map_inentry(struct proc *p, struct p_inentry *ie, vaddr_t addr, char *name, + int (*fn)(vm_map_entry_t), u_int serial) +{ + union sigval sv; + boolean_t ok = TRUE; + + if (uvm_map_inentry_recheck(serial, addr, ie)) { + KERNEL_LOCK(); + ok = uvm_map_inentry_fix(p, ie, addr, fn, serial); + if (!ok) { + printf("[%s]%d/%d %s %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + name, addr, ie->ie_start, ie->ie_end); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } + return (ok); } /* @@ -3278,6 +3342,10 @@ uvm_map_protect(struct vm_map *map, vadd if (iter->protection != old_prot) { mask = UVM_ET_ISCOPYONWRITE(iter) ? ~PROT_WRITE : PROT_MASK; + + /* XXX should only wserial++ if no split occurs */ + if (iter->protection & PROT_WRITE) + map->wserial++; /* update pmap */ if ((iter->protection & mask) == PROT_NONE && Index: uvm/uvm_map.h =================================================================== RCS file: /cvs/src/sys/uvm/uvm_map.h,v retrieving revision 1.60 diff -u -p -u -r1.60 uvm_map.h --- uvm/uvm_map.h 12 Apr 2018 17:13:44 -0000 1.60 +++ uvm/uvm_map.h 27 May 2019 12:12:43 -0000 @@ -293,6 +293,7 @@ struct vm_map { struct rwlock lock; /* Lock for map data */ struct mutex mtx; u_int serial; /* signals stack changes */ + u_int wserial; /* signals PROT_WRITE increases */ struct uvm_map_addr addr; /* Entry tree, by addr */ @@ -394,7 +395,6 @@ int uvm_map_inherit(vm_map_t, vaddr_t, int uvm_map_advice(vm_map_t, vaddr_t, vaddr_t, int); void uvm_map_init(void); boolean_t uvm_map_lookup_entry(vm_map_t, vaddr_t, vm_map_entry_t *); -boolean_t uvm_map_check_stack_range(struct proc *, vaddr_t sp); boolean_t uvm_map_is_stack_remappable(vm_map_t, vaddr_t, vsize_t); int uvm_map_remap_as_stack(struct proc *, vaddr_t, vsize_t); int uvm_map_replace(vm_map_t, vaddr_t, vaddr_t, @@ -411,6 +411,16 @@ int uvm_map_mquery(struct vm_map*, vadd void uvm_unmap_detach(struct uvm_map_deadq*, int); void uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t, struct uvm_map_deadq*, boolean_t, boolean_t); + +struct p_inentry; + +int uvm_map_inentry_recheck(u_int, vaddr_t, struct p_inentry *); +int uvm_map_inentry_sp(vm_map_entry_t); +int uvm_map_inentry_pc(vm_map_entry_t); +boolean_t uvm_map_inentry_fix(struct proc *, struct p_inentry *, + vaddr_t addr, int (*fn)(vm_map_entry_t), u_int serial); +boolean_t uvm_map_inentry(struct proc *, struct p_inentry *, vaddr_t addr, + char *name, int (*fn)(vm_map_entry_t), u_int serial); struct kinfo_vmentry; Index: arch/alpha/alpha/trap.c =================================================================== RCS file: /cvs/src/sys/arch/alpha/alpha/trap.c,v retrieving revision 1.85 diff -u -p -u -r1.85 trap.c --- arch/alpha/alpha/trap.c 12 Apr 2018 17:13:41 -0000 1.85 +++ arch/alpha/alpha/trap.c 27 May 2019 12:12:43 -0000 @@ -242,26 +242,11 @@ trap(a0, a1, a2, entry, framep) framep->tf_regs[FRAME_SP] = alpha_pal_rdusp(); user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0; if (user) { - vaddr_t sp; - p->p_md.md_tf = framep; refreshcreds(p); - - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - 0, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, entry, SEGV_ACCERR, sv); - } - - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } switch (entry) { Index: arch/amd64/amd64/trap.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/trap.c,v retrieving revision 1.74 diff -u -p -u -r1.74 trap.c --- arch/amd64/amd64/trap.c 3 Feb 2019 01:45:57 -0000 1.74 +++ arch/amd64/amd64/trap.c 27 May 2019 12:12:43 -0000 @@ -131,7 +131,6 @@ static inline void frame_dump(struct tra static inline void verify_smap(const char *_func); static inline void debug_trap(struct trapframe *_frame, struct proc *_p, long _type); -static inline void check_stack(struct proc *_p, long _type); /* * pageflttrap(frame, usermode): page fault handler @@ -328,7 +327,10 @@ usertrap(struct trapframe *frame) p->p_md.md_regs = frame; refreshcreds(p); - check_stack(p, type); + + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; switch (type) { case T_PROTFLT: /* protection fault */ @@ -454,28 +456,6 @@ debug_trap(struct trapframe *frame, stru } #endif } - -static inline void -check_stack(struct proc *p, long type) -{ - vaddr_t sp = PROC_STACK(p); - - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - union sigval sv; - - printf("trap [%s]%d/%d type %ld: sp %lx not inside" - " %lx-%lx\n", p->p_p->ps_comm, p->p_p->ps_pid, - p->p_tid, type, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, type, SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } -} - /* * ast(frame): Index: arch/arm/arm/fault.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/fault.c,v retrieving revision 1.36 diff -u -p -u -r1.36 fault.c --- arch/arm/arm/fault.c 6 Aug 2018 18:39:13 -0000 1.36 +++ arch/arm/arm/fault.c 27 May 2019 12:12:43 -0000 @@ -206,26 +206,11 @@ data_abort_handler(trapframe_t *tf) pcb = &p->p_addr->u_pcb; if (user) { - vaddr_t sp; - pcb->pcb_tf = tf; refreshcreds(p); - - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - 0, sp, p->p_spstart, p->p_spend); - - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } /* Invoke the appropriate handler, if necessary */ Index: arch/arm64/arm64/trap.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/arm64/trap.c,v retrieving revision 1.22 diff -u -p -u -r1.22 trap.c --- arch/arm64/arm64/trap.c 15 Mar 2019 05:42:38 -0000 1.22 +++ arch/arm64/arm64/trap.c 27 May 2019 12:12:43 -0000 @@ -233,7 +233,6 @@ do_el0_sync(struct trapframe *frame) union sigval sv; uint32_t exception; uint64_t esr, far; - vaddr_t sp; esr = READ_SPECIALREG(esr_el1); exception = ESR_ELx_EXCEPTION(esr); @@ -243,21 +242,9 @@ do_el0_sync(struct trapframe *frame) p->p_addr->u_pcb.pcb_tf = frame; refreshcreds(p); - - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - exception, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, exception, SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; switch(exception) { case EXCP_UNKNOWN: Index: arch/hppa/hppa/trap.c =================================================================== RCS file: /cvs/src/sys/arch/hppa/hppa/trap.c,v retrieving revision 1.143 diff -u -p -u -r1.143 trap.c --- arch/hppa/hppa/trap.c 12 Apr 2018 17:13:43 -0000 1.143 +++ arch/hppa/hppa/trap.c 27 May 2019 12:12:43 -0000 @@ -214,26 +214,10 @@ trap(int type, struct trapframe *frame) } if (type & T_USER) { - vaddr_t sp; - refreshcreds(p); - - //sp = frame->tf_sp; - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - type & ! ~T_USER, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, type & ~T_USER, - SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } switch (type) { Index: arch/i386/i386/trap.c =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/trap.c,v retrieving revision 1.138 diff -u -p -u -r1.138 trap.c --- arch/i386/i386/trap.c 9 Jul 2018 19:20:30 -0000 1.138 +++ arch/i386/i386/trap.c 27 May 2019 12:12:43 -0000 @@ -154,27 +154,12 @@ trap(struct trapframe *frame) #endif if (!KERNELMODE(frame->tf_cs, frame->tf_eflags)) { - vaddr_t sp; - type |= T_USER; p->p_md.md_regs = frame; refreshcreds(p); - - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - (int)frame->tf_trapno, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, type & ~T_USER, - SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } switch (type) { Index: arch/mips64/mips64/trap.c =================================================================== RCS file: /cvs/src/sys/arch/mips64/mips64/trap.c,v retrieving revision 1.136 diff -u -p -u -r1.136 trap.c --- arch/mips64/mips64/trap.c 15 May 2019 03:17:20 -0000 1.136 +++ arch/mips64/mips64/trap.c 27 May 2019 12:12:43 -0000 @@ -260,27 +260,10 @@ trap(struct trapframe *trapframe) #endif if (type & T_USER) { - vaddr_t sp; - refreshcreds(p); - - sp = trapframe->sp; - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - union sigval sv; - - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, type, - sp, p->p_spstart, p->p_spend); - - sv.sival_ptr = (void *)trapframe->pc; - trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); - } - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } itsa(trapframe, ci, p, type); Index: arch/powerpc/powerpc/trap.c =================================================================== RCS file: /cvs/src/sys/arch/powerpc/powerpc/trap.c,v retrieving revision 1.107 diff -u -p -u -r1.107 trap.c --- arch/powerpc/powerpc/trap.c 12 Apr 2018 17:13:44 -0000 1.107 +++ arch/powerpc/powerpc/trap.c 27 May 2019 12:12:43 -0000 @@ -234,26 +234,11 @@ trap(struct trapframe *frame) db_expr_t offset; if (frame->srr1 & PSL_PR) { - vaddr_t sp; - type |= EXC_USER; refreshcreds(p); - - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - type, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, type, SEGV_ACCERR, sv); - } - - KERNEL_UNLOCK(); - } + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; } switch (type) { Index: arch/sparc64/sparc64/trap.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/sparc64/trap.c,v retrieving revision 1.99 diff -u -p -u -r1.99 trap.c --- arch/sparc64/sparc64/trap.c 12 Apr 2018 17:13:44 -0000 1.99 +++ arch/sparc64/sparc64/trap.c 27 May 2019 12:12:43 -0000 @@ -348,7 +348,6 @@ trap(struct trapframe64 *tf, unsigned ty struct proc *p; struct pcb *pcb; int pstate = (tstate>>TSTATE_PSTATE_SHIFT); - vaddr_t sp; u_int64_t s; int64_t n; union sigval sv; @@ -427,22 +426,10 @@ trap(struct trapframe64 *tf, unsigned ty pcb = &p->p_addr->u_pcb; p->p_md.md_tf = tf; /* for ptrace/signals */ refreshcreds(p); + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "sp", + uvm_map_inentry_sp, p->p_vmspace->vm_map.serial)) + return; - sp = PROC_STACK(p); - if (p->p_vmspace->vm_map.serial != p->p_spserial || - p->p_spstart == 0 || sp < p->p_spstart || - sp >= p->p_spend) { - KERNEL_LOCK(); - if (!uvm_map_check_stack_range(p, sp)) { - printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", - p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, - (int)type, sp, p->p_spstart, p->p_spend); - sv.sival_ptr = (void *)PROC_PC(p); - trapsignal(p, SIGSEGV, type, SEGV_ACCERR, sv); - } - - KERNEL_UNLOCK(); - } switch (type) {