1 /* $OpenBSD: sendsig.c,v 1.36 2023/03/08 04:43:07 guenther Exp $ */
2
3 /*
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * William Jolitz and Don Ahn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 */
39 /*
40 * Copyright (c) 2001 Opsycon AB (www.opsycon.se)
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
52 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
55 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 */
64
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/signalvar.h>
68 #include <sys/proc.h>
69 #include <sys/exec.h>
70 #include <sys/mount.h>
71 #include <sys/syscallargs.h>
72
73 #include <uvm/uvm_extern.h>
74
75 #include <machine/regnum.h>
76 #include <mips64/mips_cpu.h>
77
78 /*
79 * WARNING: code in locore.s assumes the layout shown for sf_signum
80 * thru sf_handler so... don't screw with them!
81 */
82 struct sigframe {
83 int sf_signum; /* signo for handler */
84 siginfo_t *sf_sip; /* pointer to siginfo_t */
85 struct sigcontext *sf_scp; /* context ptr for handler */
86 sig_t sf_handler; /* handler addr for u_sigc */
87 struct sigcontext sf_sc; /* actual context */
88 siginfo_t sf_si;
89 };
90
91 /*
92 * Send an interrupt to process.
93 */
94 int
sendsig(sig_t catcher,int sig,sigset_t mask,const siginfo_t * ksip,int info,int onstack)95 sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip,
96 int info, int onstack)
97 {
98 struct cpu_info *ci = curcpu();
99 struct proc *p = ci->ci_curproc;
100 struct sigframe *fp;
101 struct trapframe *regs;
102 int fsize;
103 struct sigcontext ksc;
104
105 regs = p->p_md.md_regs;
106
107 /*
108 * Allocate space for the signal handler context.
109 */
110 fsize = sizeof(struct sigframe);
111 if (!info)
112 fsize -= sizeof(siginfo_t);
113 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
114 !sigonstack(regs->sp) && onstack)
115 fp = (struct sigframe *)
116 (trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size)
117 - fsize);
118 else
119 fp = (struct sigframe *)(regs->sp - fsize);
120 /*
121 * Build the signal context to be used by sigreturn.
122 */
123 bzero(&ksc, sizeof(ksc));
124 ksc.sc_mask = mask;
125 ksc.sc_pc = regs->pc;
126 ksc.mullo = regs->mullo;
127 ksc.mulhi = regs->mulhi;
128 bcopy((caddr_t)®s->ast, (caddr_t)&ksc.sc_regs[1],
129 sizeof(ksc.sc_regs) - sizeof(register_t));
130 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
131 if (ksc.sc_fpused) {
132 /* if FPU has current state, save it first */
133 if (p == ci->ci_fpuproc)
134 save_fpu();
135
136 bcopy((caddr_t)&p->p_md.md_regs->f0, (caddr_t)ksc.sc_fpregs,
137 sizeof(ksc.sc_fpregs));
138 }
139
140 if (info) {
141 if (copyout(ksip, (caddr_t)&fp->sf_si, sizeof *ksip))
142 return 1;
143 }
144
145 ksc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
146 if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc)))
147 return 1;
148
149 /*
150 * Build the argument list for the signal handler.
151 */
152 regs->a0 = sig;
153 regs->a1 = info ? (register_t)&fp->sf_si : 0;
154 regs->a2 = (register_t)&fp->sf_sc;
155 regs->a3 = (register_t)catcher;
156
157 regs->pc = (register_t)catcher;
158 regs->t9 = (register_t)catcher;
159 regs->sp = (register_t)fp;
160
161 regs->ra = p->p_p->ps_sigcode;
162
163 return 0;
164 }
165
166 /*
167 * System call to cleanup state after a signal
168 * has been taken. Reset signal mask and
169 * stack state from context left by sendsig (above).
170 * Return to previous pc and psl as specified by
171 * context left by sendsig. Check carefully to
172 * make sure that the user has not modified the
173 * psl to gain improper privileges or to cause
174 * a machine fault.
175 */
176 int
sys_sigreturn(struct proc * p,void * v,register_t * retval)177 sys_sigreturn(struct proc *p, void *v, register_t *retval)
178 {
179 struct cpu_info *ci = curcpu();
180 struct sys_sigreturn_args /* {
181 syscallarg(struct sigcontext *) sigcntxp;
182 } */ *uap = v;
183 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
184 struct trapframe *regs = p->p_md.md_regs;
185 int error;
186
187 if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
188 sigexit(p, SIGILL);
189 return (EPERM);
190 }
191
192 /*
193 * Test and fetch the context structure.
194 * We grab it all at once for speed.
195 */
196 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
197 if (error)
198 return (error);
199
200 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
201 sigexit(p, SIGILL);
202 return (EFAULT);
203 }
204
205 /* Prevent reuse of the sigcontext cookie */
206 ksc.sc_cookie = 0;
207 (void)copyout(&ksc.sc_cookie, (caddr_t)scp +
208 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie));
209
210 /*
211 * Restore the user supplied information
212 */
213 p->p_sigmask = ksc.sc_mask &~ sigcantmask;
214 regs->pc = ksc.sc_pc;
215 regs->mullo = ksc.mullo;
216 regs->mulhi = ksc.mulhi;
217 regs->sr &= ~SR_COP_1_BIT; /* Zap current FP state */
218 if (p == ci->ci_fpuproc)
219 ci->ci_fpuproc = NULL;
220 bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)®s->ast,
221 sizeof(ksc.sc_regs) - sizeof(register_t));
222 if (ksc.sc_fpused)
223 bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_md.md_regs->f0,
224 sizeof(ksc.sc_fpregs));
225 return (EJUSTRETURN);
226 }
227
228 void
signotify(struct proc * p)229 signotify(struct proc *p)
230 {
231 /*
232 * Ensure that preceding stores are visible to other CPUs
233 * before setting the AST flag.
234 */
235 membar_producer();
236
237 aston(p);
238 cpu_unidle(p->p_cpu);
239 }
240