1 /* $NetBSD: compat_13_machdep.c,v 1.15 2011/02/08 20:20:16 rmind Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah Hdr: machdep.c 1.74 92/12/20 37 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: compat_13_machdep.c,v 1.15 2011/02/08 20:20:16 rmind Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/proc.h> 47 #include <sys/signal.h> 48 #include <sys/signalvar.h> 49 50 #include <sys/mount.h> 51 #include <sys/syscallargs.h> 52 53 #include <compat/sys/signal.h> 54 #include <compat/sys/signalvar.h> 55 56 #include <machine/cpu.h> 57 #include <machine/reg.h> 58 59 /* 60 * System call to cleanup state after a signal 61 * has been taken. Reset signal mask and 62 * stack state from context left by sendsig (above). 63 * Return to previous pc and psl as specified by 64 * context left by sendsig. Check carefully to 65 * make sure that the user has not modified the 66 * psl to gain improper privileges or to cause 67 * a machine fault. 68 */ 69 int 70 compat_13_sys_sigreturn(struct lwp *l, const struct compat_13_sys_sigreturn_args *uap, register_t *retval) 71 { 72 /* { 73 syscallarg(struct sigcontext13 *) sigcntxp; 74 } */ 75 struct proc *p = l->l_proc; 76 struct sigcontext13 *scp; 77 struct frame *frame; 78 struct sigcontext13 tsigc; 79 sigset_t mask; 80 81 /* 82 * The trampoline code hands us the context. 83 * It is unsafe to keep track of it ourselves, in the event that a 84 * program jumps out of a signal handler. 85 */ 86 scp = SCARG(uap, sigcntxp); 87 if ((int)scp & 1) 88 return EINVAL; 89 90 if (copyin(scp, &tsigc, sizeof(tsigc)) != 0) 91 return EFAULT; 92 scp = &tsigc; 93 94 /* Make sure the user isn't pulling a fast one on us! */ 95 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) 96 return EINVAL; 97 98 /* Restore register context. */ 99 frame = (struct frame *)l->l_md.md_regs; 100 101 /* 102 * We only support restoring the sigcontext13 in this call. 103 * We are not called from the sigcode (per sendsig()), so 104 * we will not have a sigstate to restore. 105 */ 106 if (scp->sc_ap != 0) 107 return EINVAL; 108 109 /* 110 * Restore the user supplied information. 111 * This should be at the last so that the error (EINVAL) 112 * is reported to the sigreturn caller, not to the 113 * jump destination. 114 */ 115 116 frame->f_regs[SP] = scp->sc_sp; 117 frame->f_regs[A6] = scp->sc_fp; 118 frame->f_pc = scp->sc_pc; 119 frame->f_sr = scp->sc_ps; 120 121 mutex_enter(p->p_lock); 122 123 /* Restore signal stack. */ 124 if (scp->sc_onstack & SS_ONSTACK) 125 l->l_sigstk.ss_flags |= SS_ONSTACK; 126 else 127 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 128 129 /* Restore signal mask. */ 130 native_sigset13_to_sigset(&scp->sc_mask, &mask); 131 (void)sigprocmask1(l, SIG_SETMASK, &mask, 0); 132 133 mutex_exit(p->p_lock); 134 135 return EJUSTRETURN; 136 } 137