/* $OpenBSD: sendsig.c,v 1.10 2008/05/04 09:57:47 martin Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz and Don Ahn. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * Copyright (c) 2001 Opsycon AB (www.opsycon.se) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include /* * WARNING: code in locore.s assumes the layout shown for sf_signum * thru sf_handler so... don't screw with them! */ struct sigframe { int sf_signum; /* signo for handler */ siginfo_t *sf_sip; /* pointer to siginfo_t */ struct sigcontext *sf_scp; /* context ptr for handler */ sig_t sf_handler; /* handler addr for u_sigc */ struct sigcontext sf_sc; /* actual context */ siginfo_t sf_si; }; #ifdef DEBUG int sigdebug = 0; int sigpid = 0; #define SDB_FOLLOW 0x01 #define SDB_KSTACK 0x02 #define SDB_FPSTATE 0x04 #endif /* * Send an interrupt to process. */ void sendsig(catcher, sig, mask, code, type, val) sig_t catcher; int sig, mask; u_long code; int type; union sigval val; { struct proc *p = curproc; struct sigframe *fp; struct trap_frame *regs; struct sigacts *psp = p->p_sigacts; int oonstack, fsize; struct sigcontext ksc; regs = p->p_md.md_regs; oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; /* * Allocate and validate space for the signal handler * context. Note that if the stack is in data space, the * call to grow() is a nop, and the copyout() * will fail if the process has not already allocated * the space with a `brk'. */ fsize = sizeof(struct sigframe); if (!(psp->ps_siginfo & sigmask(sig))) fsize -= sizeof(siginfo_t); if ((psp->ps_flags & SAS_ALTSTACK) && (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size - fsize); psp->ps_sigstk.ss_flags |= SA_ONSTACK; } else fp = (struct sigframe *)(regs->sp - fsize); if ((vaddr_t)fp <= USRSTACK - ptoa(p->p_vmspace->vm_ssize)) (void)uvm_grow(p, (vaddr_t)fp); #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid))) printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", p->p_pid, sig, &oonstack, fp, &fp->sf_sc); #endif /* * Build the signal context to be used by sigreturn. */ ksc.sc_onstack = oonstack; ksc.sc_mask = mask; ksc.sc_pc = regs->pc; ksc.mullo = regs->mullo; ksc.mulhi = regs->mulhi; ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ bcopy((caddr_t)®s->ast, (caddr_t)&ksc.sc_regs[1], sizeof(ksc.sc_regs) - sizeof(register_t)); ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; if (ksc.sc_fpused) { extern struct proc *machFPCurProcPtr; /* if FPU has current state, save it first */ if (p == machFPCurProcPtr) { if (regs->sr & SR_FR_32) MipsSaveCurFPState(p); else MipsSaveCurFPState16(p); } bcopy((caddr_t)&p->p_md.md_regs->f0, (caddr_t)ksc.sc_fpregs, sizeof(ksc.sc_fpregs)); } if (psp->ps_siginfo & sigmask(sig)) { siginfo_t si; initsiginfo(&si, sig, code, type, val); if (copyout((caddr_t)&si, (caddr_t)&fp->sf_si, sizeof si)) goto bail; } if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) { bail: /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Build the argument list for the signal handler. */ regs->a0 = sig; regs->a1 = (psp->ps_siginfo & sigmask(sig)) ? (register_t)&fp->sf_si : NULL; regs->a2 = (register_t)&fp->sf_sc; regs->a3 = (register_t)catcher; regs->pc = (register_t)catcher; regs->t9 = (register_t)catcher; regs->sp = (register_t)fp; regs->ra = p->p_sigcode; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid))) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ /* ARGSUSED */ int sys_sigreturn(p, v, retval) struct proc *p; void *v; register_t *retval; { struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; struct sigcontext *scp; struct trap_frame *regs; struct sigcontext ksc; int error; extern struct proc *machFPCurProcPtr; scp = SCARG(uap, sigcntxp); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); #endif regs = p->p_md.md_regs; /* * Test and fetch the context structure. * We grab it all at once for speed. */ error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) { #ifdef DEBUG if (!(sigdebug & SDB_FOLLOW)) printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); printf(" old sp %x ra %x pc %x\n", regs->sp, regs->ra, regs->pc); printf(" new sp %x ra %x pc %x err %d z %x\n", ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], error, ksc.sc_regs[ZERO]); #endif return (EINVAL); } scp = &ksc; /* * Restore the user supplied information */ if (scp->sc_onstack & SA_ONSTACK) p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; else p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; p->p_sigmask = scp->sc_mask &~ sigcantmask; regs->pc = scp->sc_pc; regs->mullo = scp->mullo; regs->mulhi = scp->mulhi; regs->sr &= ~SR_COP_1_BIT; /* Zap current FP state */ if (p == machFPCurProcPtr) machFPCurProcPtr = NULL; bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)®s->ast, sizeof(scp->sc_regs) - sizeof(register_t)); if (scp->sc_fpused) bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs->f0, sizeof(scp->sc_fpregs)); return (EJUSTRETURN); }