From: miod Date: Tue, 24 Jan 2023 07:26:33 +0000 (+0000) Subject: Add and use a specific routine to fetch instructions from userland when X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=f5a006a1cb8c0501ba5edd21860410228b4c6d27;p=openbsd Add and use a specific routine to fetch instructions from userland when doing floating-point emulation, as copyin will fail on exec-only mappings now. ok deraadt@ kettenis@ --- diff --git a/sys/arch/sparc64/include/pmap.h b/sys/arch/sparc64/include/pmap.h index 6b49abd50ef..acbc71b7be3 100644 --- a/sys/arch/sparc64/include/pmap.h +++ b/sys/arch/sparc64/include/pmap.h @@ -159,7 +159,8 @@ extern struct pmap kernel_pmap_; #define pmap_proc_iflush(p,va,len) /* nothing */ -void pmap_bootstrap(u_long, u_long, u_int, u_int); +void pmap_bootstrap(u_long, u_long, u_int, u_int); +int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *); /* make sure all page mappings are modulo 16K to prevent d$ aliasing */ #define PMAP_PREFER diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c index dde9b9f9942..e067df18006 100644 --- a/sys/arch/sparc64/sparc64/pmap.c +++ b/sys/arch/sparc64/sparc64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.109 2023/01/23 19:31:41 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.110 2023/01/24 07:26:34 miod Exp $ */ /* $NetBSD: pmap.c,v 1.107 2001/08/31 16:47:41 eeh Exp $ */ /* * @@ -2915,3 +2915,25 @@ db_dump_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif) } #endif + +/* + * Read an instruction from a given virtual memory address. + * EXEC_ONLY mappings are bypassed. + */ +int +pmap_copyinsn(pmap_t pmap, vaddr_t va, uint32_t *insn) +{ + paddr_t pa; + + if (pmap == pmap_kernel()) + return EINVAL; + + mtx_enter(&pmap->pm_mtx); + /* inline pmap_extract */ + pa = pseg_get(pmap, va) & TLB_PA_MASK; + if (pa != 0) + *insn = lduwa(pa | (va & PAGE_MASK), ASI_PHYS_CACHED); + mtx_leave(&pmap->pm_mtx); + + return pa == 0 ? EFAULT : 0; +} diff --git a/sys/arch/sparc64/sparc64/trap.c b/sys/arch/sparc64/sparc64/trap.c index f697b7208dd..7321a66f9d1 100644 --- a/sys/arch/sparc64/sparc64/trap.c +++ b/sys/arch/sparc64/sparc64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.113 2023/01/16 05:32:05 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.114 2023/01/24 07:26:34 miod Exp $ */ /* $NetBSD: trap.c,v 1.73 2001/08/09 01:03:01 eeh Exp $ */ /* @@ -322,6 +322,8 @@ void text_access_error(struct trapframe *tf, unsigned type, vaddr_t pc, u_long sfsr, vaddr_t afva, u_long afsr); void syscall(struct trapframe *, register_t code, register_t pc); +int copyinsn(struct proc *p, vaddr_t uva, int *insn); + /* * If someone stole the FPU while we were away, do not enable it * on return. This is not done in userret() above as it must follow @@ -465,7 +467,7 @@ dopanic: { union instr ins; - if (copyin((caddr_t)pc, &ins, sizeof(ins)) != 0) { + if (copyinsn(p, pc, &ins.i_int) != 0) { /* XXX Can this happen? */ trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv); break; @@ -543,7 +545,7 @@ dopanic: { union instr ins; - if (copyin((caddr_t)pc, &ins, sizeof(ins)) != 0) { + if (copyinsn(p, pc, &ins.i_int) != 0) { /* XXX Can this happen? */ trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv); break; @@ -624,7 +626,8 @@ dopanic: * Push the faulting instruction on the queue; * we might need to emulate it. */ - copyin((caddr_t)pc, &p->p_md.md_fpstate->fs_queue[0].fq_instr, sizeof(int)); + (void)copyinsn(p, pc, + &p->p_md.md_fpstate->fs_queue[0].fq_instr); p->p_md.md_fpstate->fs_queue[0].fq_addr = (int *)pc; p->p_md.md_fpstate->fs_qsize = 1; } @@ -1252,3 +1255,21 @@ child_return(void *arg) mi_child_return(p); } + +int +copyinsn(struct proc *p, vaddr_t uva, int *insn) +{ + struct vm_map *map = &p->p_vmspace->vm_map; + int error = 0; + + if (__predict_false((uva & 3) != 0)) + return EFAULT; + + do { + if (pmap_copyinsn(map->pmap, uva, (uint32_t *)insn) == 0) + break; + error = uvm_fault(map, trunc_page(uva), 0, PROT_EXEC); + } while (error == 0); + + return error; +}