1 /*-
2 * Copyright (c) 2003 Peter Wemm
3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "opt_compat.h"
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/pioctl.h>
50 #include <sys/proc.h>
51 #include <sys/procfs.h>
52 #include <sys/resourcevar.h>
53 #include <sys/systm.h>
54 #include <sys/signalvar.h>
55 #include <sys/stat.h>
56 #include <sys/sx.h>
57 #include <sys/syscall.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_util.h>
71 #include <compat/freebsd32/freebsd32_proto.h>
72 #include <compat/ia32/ia32_signal.h>
73 #include <machine/psl.h>
74 #include <machine/segments.h>
75 #include <machine/specialreg.h>
76 #include <machine/frame.h>
77 #include <machine/md_var.h>
78 #include <machine/pcb.h>
79 #include <machine/cpufunc.h>
80
81 #ifdef COMPAT_FREEBSD4
82 static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long);
83 #endif
84 static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
85 static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
86
87 extern int _ucode32sel, _udatasel;
88
89 #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
90 #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
91
92 static void
93 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
94 {
95 struct savefpu *addr;
96
97 /*
98 * XXX mc_fpstate might be misaligned, since its declaration is not
99 * unportabilized using __attribute__((aligned(16))) like the
100 * declaration of struct savemm, and anyway, alignment doesn't work
101 * for auto variables since we don't use gcc's pessimal stack
102 * alignment. Work around this by abusing the spare fields after
103 * mcp->mc_fpstate.
104 *
105 * XXX unpessimize most cases by only aligning when fxsave might be
106 * called, although this requires knowing too much about
107 * fpugetregs()'s internals.
108 */
109 addr = (struct savefpu *)&mcp->mc_fpstate;
110 if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) {
111 do
112 addr = (void *)((char *)addr + 4);
113 while ((uintptr_t)(void *)addr & 0xF);
114 }
115 mcp->mc_ownedfp = fpugetregs(td, addr);
116 if (addr != (struct savefpu *)&mcp->mc_fpstate) {
117 bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
118 bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
119 }
120 mcp->mc_fpformat = fpuformat();
121 }
122
123 static int
124 ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
125 {
126 struct savefpu *addr;
127
128 if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
129 return (0);
130 else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
131 return (EINVAL);
132 else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
133 /* We don't care what state is left in the FPU or PCB. */
134 fpstate_drop(td);
135 else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
136 mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
137 /* XXX align as above. */
138 addr = (struct savefpu *)&mcp->mc_fpstate;
139 if (td == PCPU_GET(fpcurthread) &&
140 ((uintptr_t)(void *)addr & 0xF)) {
141 do
142 addr = (void *)((char *)addr + 4);
143 while ((uintptr_t)(void *)addr & 0xF);
144 bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
145 }
146 /*
147 * XXX we violate the dubious requirement that fpusetregs()
148 * be called with interrupts disabled.
149 */
150 fpusetregs(td, addr);
151 /*
152 * Don't bother putting things back where they were in the
153 * misaligned case, since we know that the caller won't use
154 * them again.
155 */
156 } else
157 return (EINVAL);
158 return (0);
159 }
160
161 /*
162 * Send an interrupt to process.
163 *
164 * Stack is set up to allow sigcode stored
165 * at top to call routine, followed by kcall
166 * to sigreturn routine below. After sigreturn
167 * resets the signal mask, the stack, and the
168 * frame pointer, it returns to the user
169 * specified pc, psl.
170 */
171 #ifdef COMPAT_FREEBSD4
172 static void
173 freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
174 {
175 struct ia32_sigframe4 sf, *sfp;
176 struct proc *p;
177 struct thread *td;
178 struct sigacts *psp;
179 struct trapframe *regs;
180 int oonstack;
181
182 td = curthread;
183 p = td->td_proc;
184 PROC_LOCK_ASSERT(p, MA_OWNED);
185 psp = p->p_sigacts;
186 mtx_assert(&psp->ps_mtx, MA_OWNED);
187 regs = td->td_frame;
188 oonstack = sigonstack(regs->tf_rsp);
189
190 /* Save user context. */
191 bzero(&sf, sizeof(sf));
192 sf.sf_uc.uc_sigmask = *mask;
193 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
194 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
195 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
196 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
197 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
198 sf.sf_uc.uc_mcontext.mc_gs = rgs();
199 sf.sf_uc.uc_mcontext.mc_fs = rfs();
200 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
201 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
202 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
203 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
204 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
205 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
206 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
207 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
208 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
209 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
210 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
211 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
212 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
213 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
214 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
215 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
216 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
217
218 /* Allocate space for the signal handler context. */
219 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
220 SIGISMEMBER(psp->ps_sigonstack, sig)) {
221 sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp +
222 td->td_sigstk.ss_size - sizeof(sf));
223 } else
224 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1;
225 PROC_UNLOCK(p);
226
227 /* Translate the signal if appropriate. */
228 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
229 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
230
231 /* Build the argument list for the signal handler. */
232 sf.sf_signum = sig;
233 sf.sf_ucontext = (register_t)&sfp->sf_uc;
234 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
235 /* Signal handler installed with SA_SIGINFO. */
236 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
237 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
238
239 /* Fill in POSIX parts */
240 sf.sf_si.si_signo = sig;
241 sf.sf_si.si_code = code;
242 sf.sf_si.si_addr = regs->tf_addr;
243 } else {
244 /* Old FreeBSD-style arguments. */
245 sf.sf_siginfo = code;
246 sf.sf_addr = regs->tf_addr;
247 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
248 }
249 mtx_unlock(&psp->ps_mtx);
250
251 /*
252 * Copy the sigframe out to the user's stack.
253 */
254 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
255 #ifdef DEBUG
256 printf("process %ld has trashed its stack\n", (long)p->p_pid);
257 #endif
258 PROC_LOCK(p);
259 sigexit(td, SIGILL);
260 }
261
262 regs->tf_rsp = (uintptr_t)sfp;
263 regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode;
264 regs->tf_rflags &= ~PSL_T;
265 regs->tf_cs = _ucode32sel;
266 regs->tf_ss = _udatasel;
267 load_ds(_udatasel);
268 td->td_pcb->pcb_ds = _udatasel;
269 load_es(_udatasel);
270 td->td_pcb->pcb_es = _udatasel;
271 /* leave user %fs and %gs untouched */
272 PROC_LOCK(p);
273 mtx_lock(&psp->ps_mtx);
274 }
275 #endif /* COMPAT_FREEBSD4 */
276
277 void
278 ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
279 {
280 struct ia32_sigframe sf, *sfp;
281 struct proc *p;
282 struct thread *td;
283 struct sigacts *psp;
284 char *sp;
285 struct trapframe *regs;
286 int oonstack;
287
288 td = curthread;
289 p = td->td_proc;
290 PROC_LOCK_ASSERT(p, MA_OWNED);
291 psp = p->p_sigacts;
292 #ifdef COMPAT_FREEBSD4
293 if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
294 freebsd4_ia32_sendsig(catcher, sig, mask, code);
295 return;
296 }
297 #endif
298 mtx_assert(&psp->ps_mtx, MA_OWNED);
299 regs = td->td_frame;
300 oonstack = sigonstack(regs->tf_rsp);
301
302 /* Save user context. */
303 bzero(&sf, sizeof(sf));
304 sf.sf_uc.uc_sigmask = *mask;
305 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
306 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
307 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
308 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
309 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
310 sf.sf_uc.uc_mcontext.mc_gs = rgs();
311 sf.sf_uc.uc_mcontext.mc_fs = rfs();
312 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
313 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
314 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
315 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
316 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
317 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
318 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
319 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
320 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
321 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
322 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
323 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
324 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
325 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
326 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
327 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
328 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
329 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
330 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
331 fpstate_drop(td);
332
333 /* Allocate space for the signal handler context. */
334 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
335 SIGISMEMBER(psp->ps_sigonstack, sig)) {
336 sp = td->td_sigstk.ss_sp +
337 td->td_sigstk.ss_size - sizeof(sf);
338 } else
339 sp = (char *)regs->tf_rsp - sizeof(sf);
340 /* Align to 16 bytes. */
341 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
342 PROC_UNLOCK(p);
343
344 /* Translate the signal if appropriate. */
345 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
346 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
347
348 /* Build the argument list for the signal handler. */
349 sf.sf_signum = sig;
350 sf.sf_ucontext = (register_t)&sfp->sf_uc;
351 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
352 /* Signal handler installed with SA_SIGINFO. */
353 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
354 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
355
356 /* Fill in POSIX parts */
357 sf.sf_si.si_signo = sig;
358 sf.sf_si.si_code = code;
359 sf.sf_si.si_addr = regs->tf_addr;
360 } else {
361 /* Old FreeBSD-style arguments. */
362 sf.sf_siginfo = code;
363 sf.sf_addr = regs->tf_addr;
364 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
365 }
366 mtx_unlock(&psp->ps_mtx);
367
368 /*
369 * Copy the sigframe out to the user's stack.
370 */
371 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
372 #ifdef DEBUG
373 printf("process %ld has trashed its stack\n", (long)p->p_pid);
374 #endif
375 PROC_LOCK(p);
376 sigexit(td, SIGILL);
377 }
378
379 regs->tf_rsp = (uintptr_t)sfp;
380 regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode);
381 regs->tf_rflags &= ~PSL_T;
382 regs->tf_cs = _ucode32sel;
383 regs->tf_ss = _udatasel;
384 load_ds(_udatasel);
385 td->td_pcb->pcb_ds = _udatasel;
386 load_es(_udatasel);
387 td->td_pcb->pcb_es = _udatasel;
388 /* leave user %fs and %gs untouched */
389 PROC_LOCK(p);
390 mtx_lock(&psp->ps_mtx);
391 }
392
393 /*
394 * System call to cleanup state after a signal
395 * has been taken. Reset signal mask and
396 * stack state from context left by sendsig (above).
397 * Return to previous pc and psl as specified by
398 * context left by sendsig. Check carefully to
399 * make sure that the user has not modified the
400 * state to gain improper privileges.
401 */
402 #ifdef COMPAT_FREEBSD4
403 /*
404 * MPSAFE
405 */
406 int
407 freebsd4_freebsd32_sigreturn(td, uap)
408 struct thread *td;
409 struct freebsd4_freebsd32_sigreturn_args /* {
410 const struct freebsd4_freebsd32_ucontext *sigcntxp;
411 } */ *uap;
412 {
413 struct ia32_ucontext4 uc;
414 struct proc *p = td->td_proc;
415 struct trapframe *regs;
416 const struct ia32_ucontext4 *ucp;
417 int cs, eflags, error;
418
419 error = copyin(uap->sigcntxp, &uc, sizeof(uc));
420 if (error != 0)
421 return (error);
422 ucp = &uc;
423 regs = td->td_frame;
424 eflags = ucp->uc_mcontext.mc_eflags;
425 /*
426 * Don't allow users to change privileged or reserved flags.
427 */
428 /*
429 * XXX do allow users to change the privileged flag PSL_RF.
430 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
431 * should sometimes set it there too. tf_eflags is kept in
432 * the signal context during signal handling and there is no
433 * other place to remember it, so the PSL_RF bit may be
434 * corrupted by the signal handler without us knowing.
435 * Corruption of the PSL_RF bit at worst causes one more or
436 * one less debugger trap, so allowing it is fairly harmless.
437 */
438 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
439 printf("freebsd4_freebsd32_sigreturn: eflags = 0x%x\n", eflags);
440 return (EINVAL);
441 }
442
443 /*
444 * Don't allow users to load a valid privileged %cs. Let the
445 * hardware check for invalid selectors, excess privilege in
446 * other selectors, invalid %eip's and invalid %esp's.
447 */
448 cs = ucp->uc_mcontext.mc_cs;
449 if (!CS_SECURE(cs)) {
450 printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
451 trapsignal(td, SIGBUS, T_PROTFLT);
452 return (EINVAL);
453 }
454
455 /* Segment selectors restored by sigtramp.S */
456 regs->tf_rdi = ucp->uc_mcontext.mc_edi;
457 regs->tf_rsi = ucp->uc_mcontext.mc_esi;
458 regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
459 regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
460 regs->tf_rdx = ucp->uc_mcontext.mc_edx;
461 regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
462 regs->tf_rax = ucp->uc_mcontext.mc_eax;
463 regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
464 regs->tf_err = ucp->uc_mcontext.mc_err;
465 regs->tf_rip = ucp->uc_mcontext.mc_eip;
466 regs->tf_cs = cs;
467 regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
468 regs->tf_rsp = ucp->uc_mcontext.mc_esp;
469 regs->tf_ss = ucp->uc_mcontext.mc_ss;
470
471 PROC_LOCK(p);
472 td->td_sigmask = ucp->uc_sigmask;
473 SIG_CANTMASK(td->td_sigmask);
474 signotify(td);
475 PROC_UNLOCK(p);
476 return (EJUSTRETURN);
477 }
478 #endif /* COMPAT_FREEBSD4 */
479
480 /*
481 * MPSAFE
482 */
483 int
484 freebsd32_sigreturn(td, uap)
485 struct thread *td;
486 struct freebsd32_sigreturn_args /* {
487 const struct freebsd32_ucontext *sigcntxp;
488 } */ *uap;
489 {
490 struct ia32_ucontext uc;
491 struct proc *p = td->td_proc;
492 struct trapframe *regs;
493 const struct ia32_ucontext *ucp;
494 int cs, eflags, error, ret;
495
496 error = copyin(uap->sigcntxp, &uc, sizeof(uc));
497 if (error != 0)
498 return (error);
499 ucp = &uc;
500 regs = td->td_frame;
501 eflags = ucp->uc_mcontext.mc_eflags;
502 /*
503 * Don't allow users to change privileged or reserved flags.
504 */
505 /*
506 * XXX do allow users to change the privileged flag PSL_RF.
507 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
508 * should sometimes set it there too. tf_eflags is kept in
509 * the signal context during signal handling and there is no
510 * other place to remember it, so the PSL_RF bit may be
511 * corrupted by the signal handler without us knowing.
512 * Corruption of the PSL_RF bit at worst causes one more or
513 * one less debugger trap, so allowing it is fairly harmless.
514 */
515 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
516 printf("freebsd32_sigreturn: eflags = 0x%x\n", eflags);
517 return (EINVAL);
518 }
519
520 /*
521 * Don't allow users to load a valid privileged %cs. Let the
522 * hardware check for invalid selectors, excess privilege in
523 * other selectors, invalid %eip's and invalid %esp's.
524 */
525 cs = ucp->uc_mcontext.mc_cs;
526 if (!CS_SECURE(cs)) {
527 printf("sigreturn: cs = 0x%x\n", cs);
528 trapsignal(td, SIGBUS, T_PROTFLT);
529 return (EINVAL);
530 }
531
532 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext);
533 if (ret != 0)
534 return (ret);
535
536 /* Segment selectors restored by sigtramp.S */
537 regs->tf_rdi = ucp->uc_mcontext.mc_edi;
538 regs->tf_rsi = ucp->uc_mcontext.mc_esi;
539 regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
540 regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
541 regs->tf_rdx = ucp->uc_mcontext.mc_edx;
542 regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
543 regs->tf_rax = ucp->uc_mcontext.mc_eax;
544 regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
545 regs->tf_err = ucp->uc_mcontext.mc_err;
546 regs->tf_rip = ucp->uc_mcontext.mc_eip;
547 regs->tf_cs = cs;
548 regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
549 regs->tf_rsp = ucp->uc_mcontext.mc_esp;
550 regs->tf_ss = ucp->uc_mcontext.mc_ss;
551
552 PROC_LOCK(p);
553 td->td_sigmask = ucp->uc_sigmask;
554 SIG_CANTMASK(td->td_sigmask);
555 signotify(td);
556 PROC_UNLOCK(p);
557 return (EJUSTRETURN);
558 }
559
560 /*
561 * Clear registers on exec
562 */
563 void
564 ia32_setregs(td, entry, stack, ps_strings)
565 struct thread *td;
566 u_long entry;
567 u_long stack;
568 u_long ps_strings;
569 {
570 struct trapframe *regs = td->td_frame;
571 struct pcb *pcb = td->td_pcb;
572
573 wrmsr(MSR_FSBASE, 0);
574 wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
575 pcb->pcb_fsbase = 0;
576 pcb->pcb_gsbase = 0;
577 load_ds(_udatasel);
578 load_es(_udatasel);
579 load_fs(_udatasel);
580 load_gs(_udatasel);
581 pcb->pcb_ds = _udatasel;
582 pcb->pcb_es = _udatasel;
583 pcb->pcb_fs = _udatasel;
584 pcb->pcb_gs = _udatasel;
585
586 bzero((char *)regs, sizeof(struct trapframe));
587 regs->tf_rip = entry;
588 regs->tf_rsp = stack;
589 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
590 regs->tf_ss = _udatasel;
591 regs->tf_cs = _ucode32sel;
592 regs->tf_rbx = ps_strings;
593 load_cr0(rcr0() | CR0_MP | CR0_TS);
594 fpstate_drop(td);
595
596 /* Return via doreti so that we can change to a different %cs */
597 pcb->pcb_flags |= PCB_FULLCTX;
598 td->td_retval[1] = 0;
599 }
Cache object: 46bfbb7435954f7672b31cc303dccbfb
|