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