]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/ia32/ia32_signal.c
sqlite3: Vendor import of sqlite3 3.42.0
[FreeBSD/FreeBSD.git] / sys / amd64 / ia32 / ia32_signal.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2003 Peter Wemm
5  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * William Jolitz.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/exec.h>
41 #include <sys/fcntl.h>
42 #include <sys/imgact.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mutex.h>
47 #include <sys/mman.h>
48 #include <sys/namei.h>
49 #include <sys/proc.h>
50 #include <sys/procfs.h>
51 #include <sys/resourcevar.h>
52 #include <sys/systm.h>
53 #include <sys/signalvar.h>
54 #include <sys/stat.h>
55 #include <sys/sx.h>
56 #include <sys/syscall.h>
57 #include <sys/syscallsubr.h>
58 #include <sys/sysctl.h>
59 #include <sys/sysent.h>
60 #include <sys/vnode.h>
61
62 #include <vm/vm.h>
63 #include <vm/vm_kern.h>
64 #include <vm/vm_param.h>
65 #include <vm/pmap.h>
66 #include <vm/vm_map.h>
67 #include <vm/vm_object.h>
68 #include <vm/vm_extern.h>
69
70 #include <compat/freebsd32/freebsd32_signal.h>
71 #include <compat/freebsd32/freebsd32_util.h>
72 #include <compat/freebsd32/freebsd32_proto.h>
73 #include <compat/freebsd32/freebsd32.h>
74 #include <compat/ia32/ia32_signal.h>
75 #include <machine/psl.h>
76 #include <machine/segments.h>
77 #include <machine/specialreg.h>
78 #include <machine/frame.h>
79 #include <machine/md_var.h>
80 #include <machine/pcb.h>
81 #include <machine/cpufunc.h>
82 #include <machine/trap.h>
83
84 #include "vdso_ia32_offsets.h"
85
86 extern const char _binary_elf_vdso32_so_1_start[];
87 extern const char _binary_elf_vdso32_so_1_end[];
88 extern char _binary_elf_vdso32_so_1_size;
89
90 #ifdef COMPAT_FREEBSD4
91 static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
92 #endif
93
94 static void
95 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
96     char **xfpusave, size_t *xfpusave_len)
97 {
98         /*
99          * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE
100          * in 32bit mode saves %cs and %ds, while on 64bit it saves
101          * 64bit instruction and data pointers. Ignore the difference
102          * for now, it should be irrelevant for most applications.
103          */
104         mcp->mc_ownedfp = fpugetregs(td);
105         bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0],
106             sizeof(mcp->mc_fpstate));
107         mcp->mc_fpformat = fpuformat();
108         if (xfpusave == NULL)
109                 return;
110         if (!use_xsave || cpu_max_ext_state_size <= sizeof(struct savefpu)) {
111                 *xfpusave_len = 0;
112                 *xfpusave = NULL;
113         } else {
114                 mcp->mc_flags |= _MC_IA32_HASFPXSTATE;
115                 *xfpusave_len = mcp->mc_xfpustate_len =
116                     cpu_max_ext_state_size - sizeof(struct savefpu);
117                 *xfpusave = (char *)(get_pcb_user_save_td(td) + 1);
118         }
119 }
120
121 static int
122 ia32_set_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
123     char *xfpustate, size_t xfpustate_len)
124 {
125         int error;
126
127         if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
128                 return (0);
129         else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
130                 return (EINVAL);
131         else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
132                 /* We don't care what state is left in the FPU or PCB. */
133                 fpstate_drop(td);
134                 error = 0;
135         } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
136             mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
137                 error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate,
138                     xfpustate, xfpustate_len);
139         } else
140                 return (EINVAL);
141         return (error);
142 }
143
144 /*
145  * Get machine context.
146  */
147 static int
148 ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
149 {
150         struct pcb *pcb;
151         struct trapframe *tp;
152
153         pcb = td->td_pcb;
154         tp = td->td_frame;
155
156         PROC_LOCK(curthread->td_proc);
157         mcp->mc_onstack = sigonstack(tp->tf_rsp);
158         PROC_UNLOCK(curthread->td_proc);
159         /* Entry into kernel always sets TF_HASSEGS */
160         mcp->mc_gs = tp->tf_gs;
161         mcp->mc_fs = tp->tf_fs;
162         mcp->mc_es = tp->tf_es;
163         mcp->mc_ds = tp->tf_ds;
164         mcp->mc_edi = tp->tf_rdi;
165         mcp->mc_esi = tp->tf_rsi;
166         mcp->mc_ebp = tp->tf_rbp;
167         mcp->mc_isp = tp->tf_rsp;
168         mcp->mc_eflags = tp->tf_rflags;
169         if (flags & GET_MC_CLEAR_RET) {
170                 mcp->mc_eax = 0;
171                 mcp->mc_edx = 0;
172                 mcp->mc_eflags &= ~PSL_C;
173         } else {
174                 mcp->mc_eax = tp->tf_rax;
175                 mcp->mc_edx = tp->tf_rdx;
176         }
177         mcp->mc_ebx = tp->tf_rbx;
178         mcp->mc_ecx = tp->tf_rcx;
179         mcp->mc_eip = tp->tf_rip;
180         mcp->mc_cs = tp->tf_cs;
181         mcp->mc_esp = tp->tf_rsp;
182         mcp->mc_ss = tp->tf_ss;
183         mcp->mc_len = sizeof(*mcp);
184         mcp->mc_flags = tp->tf_flags;
185         ia32_get_fpcontext(td, mcp, NULL, 0);
186         mcp->mc_fsbase = pcb->pcb_fsbase;
187         mcp->mc_gsbase = pcb->pcb_gsbase;
188         mcp->mc_xfpustate = 0;
189         mcp->mc_xfpustate_len = 0;
190         bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
191         return (0);
192 }
193
194 /*
195  * Set machine context.
196  *
197  * However, we don't set any but the user modifiable flags, and we won't
198  * touch the cs selector.
199  */
200 static int
201 ia32_set_mcontext(struct thread *td, struct ia32_mcontext *mcp)
202 {
203         struct trapframe *tp;
204         char *xfpustate;
205         long rflags;
206         int ret;
207
208         tp = td->td_frame;
209         if (mcp->mc_len != sizeof(*mcp))
210                 return (EINVAL);
211         rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
212             (tp->tf_rflags & ~PSL_USERCHANGE);
213         if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) {
214                 if (mcp->mc_xfpustate_len > cpu_max_ext_state_size -
215                     sizeof(struct savefpu))
216                         return (EINVAL);
217                 xfpustate = (char *)fpu_save_area_alloc();
218                 ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate,
219                     mcp->mc_xfpustate_len);
220                 if (ret != 0) {
221                         fpu_save_area_free((struct savefpu *)xfpustate);
222                         return (ret);
223                 }
224         } else
225                 xfpustate = NULL;
226         ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len);
227         fpu_save_area_free((struct savefpu *)xfpustate);
228         if (ret != 0)
229                 return (ret);
230         tp->tf_gs = mcp->mc_gs;
231         tp->tf_fs = mcp->mc_fs;
232         tp->tf_es = mcp->mc_es;
233         tp->tf_ds = mcp->mc_ds;
234         tp->tf_flags = TF_HASSEGS;
235         tp->tf_rdi = mcp->mc_edi;
236         tp->tf_rsi = mcp->mc_esi;
237         tp->tf_rbp = mcp->mc_ebp;
238         tp->tf_rbx = mcp->mc_ebx;
239         tp->tf_rdx = mcp->mc_edx;
240         tp->tf_rcx = mcp->mc_ecx;
241         tp->tf_rax = mcp->mc_eax;
242         /* trapno, err */
243         tp->tf_rip = mcp->mc_eip;
244         tp->tf_rflags = rflags;
245         tp->tf_rsp = mcp->mc_esp;
246         tp->tf_ss = mcp->mc_ss;
247         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
248         return (0);
249 }
250
251 /*
252  * The first two fields of a ucontext_t are the signal mask and
253  * the machine context.  The next field is uc_link; we want to
254  * avoid destroying the link when copying out contexts.
255  */
256 #define UC_COPY_SIZE    offsetof(struct ia32_ucontext, uc_link)
257
258 int
259 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
260 {
261         struct ia32_ucontext uc;
262         int ret;
263
264         if (uap->ucp == NULL)
265                 ret = EINVAL;
266         else {
267                 bzero(&uc, sizeof(uc));
268                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
269                 PROC_LOCK(td->td_proc);
270                 uc.uc_sigmask = td->td_sigmask;
271                 PROC_UNLOCK(td->td_proc);
272                 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
273         }
274         return (ret);
275 }
276
277 int
278 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
279 {
280         struct ia32_ucontext uc;
281         int ret;
282
283         if (uap->ucp == NULL)
284                 ret = EINVAL;
285         else {
286                 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
287                 if (ret == 0) {
288                         ret = ia32_set_mcontext(td, &uc.uc_mcontext);
289                         if (ret == 0) {
290                                 kern_sigprocmask(td, SIG_SETMASK,
291                                     &uc.uc_sigmask, NULL, 0);
292                         }
293                 }
294         }
295         return (ret == 0 ? EJUSTRETURN : ret);
296 }
297
298 int
299 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
300 {
301         struct ia32_ucontext uc;
302         int ret;
303
304         if (uap->oucp == NULL || uap->ucp == NULL)
305                 ret = EINVAL;
306         else {
307                 bzero(&uc, sizeof(uc));
308                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
309                 PROC_LOCK(td->td_proc);
310                 uc.uc_sigmask = td->td_sigmask;
311                 PROC_UNLOCK(td->td_proc);
312                 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
313                 if (ret == 0) {
314                         ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
315                         if (ret == 0) {
316                                 ret = ia32_set_mcontext(td, &uc.uc_mcontext);
317                                 if (ret == 0) {
318                                         kern_sigprocmask(td, SIG_SETMASK,
319                                             &uc.uc_sigmask, NULL, 0);
320                                 }
321                         }
322                 }
323         }
324         return (ret == 0 ? EJUSTRETURN : ret);
325 }
326
327 /*
328  * Send an interrupt to process.
329  *
330  * Stack is set up to allow sigcode stored
331  * at top to call routine, followed by kcall
332  * to sigreturn routine below.  After sigreturn
333  * resets the signal mask, the stack, and the
334  * frame pointer, it returns to the user
335  * specified pc, psl.
336  */
337
338 #ifdef COMPAT_43
339 static void
340 ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
341 {
342         struct ia32_osigframe sf, *fp;
343         struct proc *p;
344         struct thread *td;
345         struct sigacts *psp;
346         struct trapframe *regs;
347         int sig;
348         int oonstack;
349
350         td = curthread;
351         p = td->td_proc;
352         PROC_LOCK_ASSERT(p, MA_OWNED);
353         sig = ksi->ksi_signo;
354         psp = p->p_sigacts;
355         mtx_assert(&psp->ps_mtx, MA_OWNED);
356         regs = td->td_frame;
357         oonstack = sigonstack(regs->tf_rsp);
358
359         /* Allocate space for the signal handler context. */
360         if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
361             SIGISMEMBER(psp->ps_sigonstack, sig)) {
362                 fp = (struct ia32_osigframe *)((uintptr_t)td->td_sigstk.ss_sp +
363                     td->td_sigstk.ss_size - sizeof(sf));
364                 td->td_sigstk.ss_flags |= SS_ONSTACK;
365         } else
366                 fp = (struct ia32_osigframe *)regs->tf_rsp - 1;
367
368         /* Build the argument list for the signal handler. */
369         sf.sf_signum = sig;
370         sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
371         bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo));
372         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
373                 /* Signal handler installed with SA_SIGINFO. */
374                 sf.sf_arg2 = (register_t)&fp->sf_siginfo;
375                 sf.sf_siginfo.si_signo = sig;
376                 sf.sf_siginfo.si_code = ksi->ksi_code;
377                 sf.sf_ah = (uintptr_t)catcher;
378                 sf.sf_addr = 0;
379         } else {
380                 /* Old FreeBSD-style arguments. */
381                 sf.sf_arg2 = ksi->ksi_code;
382                 sf.sf_addr = (register_t)ksi->ksi_addr;
383                 sf.sf_ah = (uintptr_t)catcher;
384         }
385         mtx_unlock(&psp->ps_mtx);
386         PROC_UNLOCK(p);
387
388         /* Save most if not all of trap frame. */
389         sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax;
390         sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx;
391         sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx;
392         sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx;
393         sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi;
394         sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi;
395         sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
396         sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
397         sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
398         sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
399         sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
400         sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs;
401         sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp;
402
403         /* Build the signal context to be used by osigreturn(). */
404         sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
405         SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
406         sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp;
407         sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp;
408         sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip;
409         sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags;
410         sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
411         sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
412
413         /*
414          * Copy the sigframe out to the user's stack.
415          */
416         if (copyout(&sf, fp, sizeof(*fp)) != 0) {
417 #ifdef DEBUG
418                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
419 #endif
420                 PROC_LOCK(p);
421                 sigexit(td, SIGILL);
422         }
423
424         regs->tf_rsp = (uintptr_t)fp;
425         regs->tf_rip = PROC_PS_STRINGS(p) -
426             (_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
427             VDSO_IA32_OSIGCODE_OFFSET;
428         regs->tf_rflags &= ~(PSL_T | PSL_D);
429         regs->tf_cs = _ucode32sel;
430         regs->tf_ds = _udatasel;
431         regs->tf_es = _udatasel;
432         regs->tf_fs = _udatasel;
433         regs->tf_ss = _udatasel;
434         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
435         PROC_LOCK(p);
436         mtx_lock(&psp->ps_mtx);
437 }
438 #endif
439
440 #ifdef COMPAT_FREEBSD4
441 static void
442 freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
443 {
444         struct ia32_freebsd4_sigframe sf, *sfp;
445         struct siginfo32 siginfo;
446         struct proc *p;
447         struct thread *td;
448         struct sigacts *psp;
449         struct trapframe *regs;
450         int oonstack;
451         int sig;
452
453         td = curthread;
454         p = td->td_proc;
455         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
456
457         PROC_LOCK_ASSERT(p, MA_OWNED);
458         sig = siginfo.si_signo;
459         psp = p->p_sigacts;
460         mtx_assert(&psp->ps_mtx, MA_OWNED);
461         regs = td->td_frame;
462         oonstack = sigonstack(regs->tf_rsp);
463
464         /* Save user context. */
465         bzero(&sf, sizeof(sf));
466         sf.sf_uc.uc_sigmask = *mask;
467         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
468         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
469         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
470             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
471         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
472         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
473         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
474         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
475         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
476         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
477         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
478         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
479         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
480         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
481         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
482         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
483         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
484         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
485         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
486         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
487         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
488         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
489         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
490         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
491         bzero(sf.sf_uc.uc_mcontext.mc_fpregs,
492             sizeof(sf.sf_uc.uc_mcontext.mc_fpregs));
493         bzero(sf.sf_uc.uc_mcontext.__spare__,
494             sizeof(sf.sf_uc.uc_mcontext.__spare__));
495         bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
496
497         /* Allocate space for the signal handler context. */
498         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
499             SIGISMEMBER(psp->ps_sigonstack, sig)) {
500                 sfp = (struct ia32_freebsd4_sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
501                     td->td_sigstk.ss_size - sizeof(sf));
502         } else
503                 sfp = (struct ia32_freebsd4_sigframe *)regs->tf_rsp - 1;
504         PROC_UNLOCK(p);
505
506         /* Build the argument list for the signal handler. */
507         sf.sf_signum = sig;
508         sf.sf_ucontext = (register_t)&sfp->sf_uc;
509         bzero(&sf.sf_si, sizeof(sf.sf_si));
510         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
511                 /* Signal handler installed with SA_SIGINFO. */
512                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
513                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
514
515                 /* Fill in POSIX parts */
516                 sf.sf_si = siginfo;
517                 sf.sf_si.si_signo = sig;
518         } else {
519                 /* Old FreeBSD-style arguments. */
520                 sf.sf_siginfo = siginfo.si_code;
521                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
522                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
523         }
524         mtx_unlock(&psp->ps_mtx);
525
526         /*
527          * Copy the sigframe out to the user's stack.
528          */
529         if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
530 #ifdef DEBUG
531                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
532 #endif
533                 PROC_LOCK(p);
534                 sigexit(td, SIGILL);
535         }
536
537         regs->tf_rsp = (uintptr_t)sfp;
538         regs->tf_rip = PROC_SIGCODE(p) +
539             VDSO_FREEBSD4_IA32_SIGCODE_OFFSET - VDSO_IA32_SIGCODE_OFFSET;
540         regs->tf_rflags &= ~(PSL_T | PSL_D);
541         regs->tf_cs = _ucode32sel;
542         regs->tf_ss = _udatasel;
543         regs->tf_ds = _udatasel;
544         regs->tf_es = _udatasel;
545         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
546         /* leave user %fs and %gs untouched */
547         PROC_LOCK(p);
548         mtx_lock(&psp->ps_mtx);
549 }
550 #endif  /* COMPAT_FREEBSD4 */
551
552 void
553 ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
554 {
555         struct ia32_sigframe sf, *sfp;
556         struct siginfo32 siginfo;
557         struct proc *p;
558         struct thread *td;
559         struct sigacts *psp;
560         char *sp;
561         struct trapframe *regs;
562         char *xfpusave;
563         size_t xfpusave_len;
564         int oonstack;
565         int sig;
566
567         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
568         td = curthread;
569         p = td->td_proc;
570         PROC_LOCK_ASSERT(p, MA_OWNED);
571         sig = siginfo.si_signo;
572         psp = p->p_sigacts;
573 #ifdef COMPAT_FREEBSD4
574         if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
575                 freebsd4_ia32_sendsig(catcher, ksi, mask);
576                 return;
577         }
578 #endif
579 #ifdef COMPAT_43
580         if (SIGISMEMBER(psp->ps_osigset, sig)) {
581                 ia32_osendsig(catcher, ksi, mask);
582                 return;
583         }
584 #endif
585         mtx_assert(&psp->ps_mtx, MA_OWNED);
586         regs = td->td_frame;
587         oonstack = sigonstack(regs->tf_rsp);
588
589         /* Save user context. */
590         bzero(&sf, sizeof(sf));
591         sf.sf_uc.uc_sigmask = *mask;
592         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
593         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
594         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
595             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
596         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
597         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
598         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
599         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
600         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
601         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
602         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
603         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
604         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
605         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
606         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
607         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
608         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
609         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
610         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
611         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
612         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
613         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
614         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
615         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
616         sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
617         ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, &xfpusave, &xfpusave_len);
618         sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
619         sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
620
621         /* Allocate space for the signal handler context. */
622         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
623             SIGISMEMBER(psp->ps_sigonstack, sig))
624                 sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
625         else
626                 sp = (char *)regs->tf_rsp;
627         if (xfpusave != NULL) {
628                 sp -= xfpusave_len;
629                 sp = (char *)((unsigned long)sp & ~0x3Ful);
630                 sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
631         }
632         sp -= sizeof(sf);
633         /* Align to 16 bytes. */
634         sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
635         PROC_UNLOCK(p);
636
637         /* Build the argument list for the signal handler. */
638         sf.sf_signum = sig;
639         sf.sf_ucontext = (register_t)&sfp->sf_uc;
640         bzero(&sf.sf_si, sizeof(sf.sf_si));
641         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
642                 /* Signal handler installed with SA_SIGINFO. */
643                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
644                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
645
646                 /* Fill in POSIX parts */
647                 sf.sf_si = siginfo;
648                 sf.sf_si.si_signo = sig;
649         } else {
650                 /* Old FreeBSD-style arguments. */
651                 sf.sf_siginfo = siginfo.si_code;
652                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
653                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
654         }
655         mtx_unlock(&psp->ps_mtx);
656
657         /*
658          * Copy the sigframe out to the user's stack.
659          */
660         if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
661             (xfpusave != NULL && copyout(xfpusave,
662             PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len)
663             != 0)) {
664 #ifdef DEBUG
665                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
666 #endif
667                 PROC_LOCK(p);
668                 sigexit(td, SIGILL);
669         }
670
671         fpstate_drop(td);
672         regs->tf_rsp = (uintptr_t)sfp;
673         regs->tf_rip = PROC_SIGCODE(p);
674         regs->tf_rflags &= ~(PSL_T | PSL_D);
675         regs->tf_cs = _ucode32sel;
676         regs->tf_ss = _udatasel;
677         regs->tf_ds = _udatasel;
678         regs->tf_es = _udatasel;
679         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
680         /* XXXKIB leave user %fs and %gs untouched */
681         PROC_LOCK(p);
682         mtx_lock(&psp->ps_mtx);
683 }
684
685 /*
686  * System call to cleanup state after a signal
687  * has been taken.  Reset signal mask and
688  * stack state from context left by sendsig (above).
689  * Return to previous pc and psl as specified by
690  * context left by sendsig. Check carefully to
691  * make sure that the user has not modified the
692  * state to gain improper privileges.
693  */
694
695 #ifdef COMPAT_43
696 int
697 ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
698 {
699         struct ia32_osigcontext sc, *scp;
700         struct trapframe *regs;
701         int eflags, error;
702         ksiginfo_t ksi;
703
704         regs = td->td_frame;
705         error = copyin(uap->sigcntxp, &sc, sizeof(sc));
706         if (error != 0)
707                 return (error);
708         scp = &sc;
709         eflags = scp->sc_eflags;
710         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
711                 return (EINVAL);
712         }
713         if (!CS_SECURE(scp->sc_cs)) {
714                 ksiginfo_init_trap(&ksi);
715                 ksi.ksi_signo = SIGBUS;
716                 ksi.ksi_code = BUS_OBJERR;
717                 ksi.ksi_trapno = T_PROTFLT;
718                 ksi.ksi_addr = (void *)regs->tf_rip;
719                 trapsignal(td, &ksi);
720                 return (EINVAL);
721         }
722         regs->tf_ds = scp->sc_ds;
723         regs->tf_es = scp->sc_es;
724         regs->tf_fs = scp->sc_fs;
725         regs->tf_gs = scp->sc_gs;
726
727         regs->tf_rax = scp->sc_eax;
728         regs->tf_rbx = scp->sc_ebx;
729         regs->tf_rcx = scp->sc_ecx;
730         regs->tf_rdx = scp->sc_edx;
731         regs->tf_rsi = scp->sc_esi;
732         regs->tf_rdi = scp->sc_edi;
733         regs->tf_cs = scp->sc_cs;
734         regs->tf_ss = scp->sc_ss;
735         regs->tf_rbp = scp->sc_ebp;
736         regs->tf_rsp = scp->sc_esp;
737         regs->tf_rip = scp->sc_eip;
738         regs->tf_rflags = eflags;
739
740         if (scp->sc_onstack & 1)
741                 td->td_sigstk.ss_flags |= SS_ONSTACK;
742         else
743                 td->td_sigstk.ss_flags &= ~SS_ONSTACK;
744
745         kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
746             SIGPROCMASK_OLD);
747         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
748         return (EJUSTRETURN);
749 }
750 #endif
751
752 #ifdef COMPAT_FREEBSD4
753 int
754 freebsd4_freebsd32_sigreturn(struct thread *td,
755     struct freebsd4_freebsd32_sigreturn_args *uap)
756 {
757         struct ia32_freebsd4_ucontext uc;
758         struct trapframe *regs;
759         struct ia32_freebsd4_ucontext *ucp;
760         int cs, eflags, error;
761         ksiginfo_t ksi;
762
763         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
764         if (error != 0)
765                 return (error);
766         ucp = &uc;
767         regs = td->td_frame;
768         eflags = ucp->uc_mcontext.mc_eflags;
769         /*
770          * Don't allow users to change privileged or reserved flags.
771          */
772         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
773                 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n",
774                     td->td_proc->p_pid, td->td_name, eflags);
775                 return (EINVAL);
776         }
777
778         /*
779          * Don't allow users to load a valid privileged %cs.  Let the
780          * hardware check for invalid selectors, excess privilege in
781          * other selectors, invalid %eip's and invalid %esp's.
782          */
783         cs = ucp->uc_mcontext.mc_cs;
784         if (!CS_SECURE(cs)) {
785                 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
786                     td->td_proc->p_pid, td->td_name, cs);
787                 ksiginfo_init_trap(&ksi);
788                 ksi.ksi_signo = SIGBUS;
789                 ksi.ksi_code = BUS_OBJERR;
790                 ksi.ksi_trapno = T_PROTFLT;
791                 ksi.ksi_addr = (void *)regs->tf_rip;
792                 trapsignal(td, &ksi);
793                 return (EINVAL);
794         }
795
796         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
797         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
798         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
799         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
800         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
801         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
802         regs->tf_rax = ucp->uc_mcontext.mc_eax;
803         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
804         regs->tf_err = ucp->uc_mcontext.mc_err;
805         regs->tf_rip = ucp->uc_mcontext.mc_eip;
806         regs->tf_cs = cs;
807         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
808         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
809         regs->tf_ss = ucp->uc_mcontext.mc_ss;
810         regs->tf_ds = ucp->uc_mcontext.mc_ds;
811         regs->tf_es = ucp->uc_mcontext.mc_es;
812         regs->tf_fs = ucp->uc_mcontext.mc_fs;
813         regs->tf_gs = ucp->uc_mcontext.mc_gs;
814
815         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
816         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
817         return (EJUSTRETURN);
818 }
819 #endif  /* COMPAT_FREEBSD4 */
820
821 int
822 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
823 {
824         struct ia32_ucontext uc;
825         struct trapframe *regs;
826         struct ia32_ucontext *ucp;
827         char *xfpustate;
828         size_t xfpustate_len;
829         int cs, eflags, error, ret;
830         ksiginfo_t ksi;
831
832         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
833         if (error != 0)
834                 return (error);
835         ucp = &uc;
836         regs = td->td_frame;
837         eflags = ucp->uc_mcontext.mc_eflags;
838         /*
839          * Don't allow users to change privileged or reserved flags.
840          */
841         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
842                 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n",
843                     td->td_proc->p_pid, td->td_name, eflags);
844                 return (EINVAL);
845         }
846
847         /*
848          * Don't allow users to load a valid privileged %cs.  Let the
849          * hardware check for invalid selectors, excess privilege in
850          * other selectors, invalid %eip's and invalid %esp's.
851          */
852         cs = ucp->uc_mcontext.mc_cs;
853         if (!CS_SECURE(cs)) {
854                 uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
855                     td->td_proc->p_pid, td->td_name, cs);
856                 ksiginfo_init_trap(&ksi);
857                 ksi.ksi_signo = SIGBUS;
858                 ksi.ksi_code = BUS_OBJERR;
859                 ksi.ksi_trapno = T_PROTFLT;
860                 ksi.ksi_addr = (void *)regs->tf_rip;
861                 trapsignal(td, &ksi);
862                 return (EINVAL);
863         }
864
865         if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) {
866                 xfpustate_len = uc.uc_mcontext.mc_xfpustate_len;
867                 if (xfpustate_len > cpu_max_ext_state_size -
868                     sizeof(struct savefpu)) {
869                         uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n",
870                             td->td_proc->p_pid, td->td_name, xfpustate_len);
871                         return (EINVAL);
872                 }
873                 xfpustate = (char *)fpu_save_area_alloc();
874                 error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate),
875                     xfpustate, xfpustate_len);
876                 if (error != 0) {
877                         fpu_save_area_free((struct savefpu *)xfpustate);
878                         uprintf(
879         "pid %d (%s): sigreturn copying xfpustate failed\n",
880                             td->td_proc->p_pid, td->td_name);
881                         return (error);
882                 }
883         } else {
884                 xfpustate = NULL;
885                 xfpustate_len = 0;
886         }
887         ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate,
888             xfpustate_len);
889         fpu_save_area_free((struct savefpu *)xfpustate);
890         if (ret != 0) {
891                 uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n",
892                     td->td_proc->p_pid, td->td_name, ret);
893                 return (ret);
894         }
895
896         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
897         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
898         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
899         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
900         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
901         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
902         regs->tf_rax = ucp->uc_mcontext.mc_eax;
903         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
904         regs->tf_err = ucp->uc_mcontext.mc_err;
905         regs->tf_rip = ucp->uc_mcontext.mc_eip;
906         regs->tf_cs = cs;
907         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
908         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
909         regs->tf_ss = ucp->uc_mcontext.mc_ss;
910         regs->tf_ds = ucp->uc_mcontext.mc_ds;
911         regs->tf_es = ucp->uc_mcontext.mc_es;
912         regs->tf_fs = ucp->uc_mcontext.mc_fs;
913         regs->tf_gs = ucp->uc_mcontext.mc_gs;
914         regs->tf_flags = TF_HASSEGS;
915
916         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
917         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
918         return (EJUSTRETURN);
919 }
920
921 /*
922  * Clear registers on exec
923  */
924 void
925 ia32_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
926 {
927         struct trapframe *regs;
928         struct pcb *pcb;
929         register_t saved_rflags;
930
931         regs = td->td_frame;
932         pcb = td->td_pcb;
933
934         if (td->td_proc->p_md.md_ldt != NULL)
935                 user_ldt_free(td);
936 #ifdef COMPAT_43
937         setup_lcall_gate();
938 #endif
939
940         pcb->pcb_fsbase = 0;
941         pcb->pcb_gsbase = 0;
942         pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
943
944         saved_rflags = regs->tf_rflags & PSL_T;
945         bzero((char *)regs, sizeof(struct trapframe));
946         regs->tf_rip = imgp->entry_addr;
947         regs->tf_rsp = stack;
948         regs->tf_rflags = PSL_USER | saved_rflags;
949         regs->tf_ss = _udatasel;
950         regs->tf_cs = _ucode32sel;
951         regs->tf_rbx = (register_t)imgp->ps_strings;
952         regs->tf_ds = _udatasel;
953         regs->tf_es = _udatasel;
954         regs->tf_fs = _ufssel;
955         regs->tf_gs = _ugssel;
956         regs->tf_flags = TF_HASSEGS;
957
958         x86_clear_dbregs(pcb);
959
960         fpstate_drop(td);
961
962         /* Return via doreti so that we can change to a different %cs */
963         set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
964 }