1 | /* $NetBSD: netbsd32_signal.c,v 1.43 2016/09/18 05:16:21 christos Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1998, 2001 Matthew R. Green |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.43 2016/09/18 05:16:21 christos Exp $" ); |
31 | |
32 | #if defined(_KERNEL_OPT) |
33 | #include "opt_ktrace.h" |
34 | #endif |
35 | |
36 | #include <sys/param.h> |
37 | #include <sys/systm.h> |
38 | #include <sys/mount.h> |
39 | #include <sys/stat.h> |
40 | #include <sys/time.h> |
41 | #include <sys/signalvar.h> |
42 | #include <sys/ktrace.h> |
43 | #include <sys/proc.h> |
44 | #include <sys/wait.h> |
45 | #include <sys/dirent.h> |
46 | |
47 | #include <uvm/uvm_extern.h> |
48 | |
49 | #include <compat/netbsd32/netbsd32.h> |
50 | #include <compat/netbsd32/netbsd32_conv.h> |
51 | #include <compat/netbsd32/netbsd32_syscallargs.h> |
52 | |
53 | #include <compat/sys/signal.h> |
54 | #include <compat/sys/signalvar.h> |
55 | #include <compat/sys/siginfo.h> |
56 | #include <compat/sys/ucontext.h> |
57 | #include <compat/common/compat_sigaltstack.h> |
58 | |
59 | int |
60 | netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval) |
61 | { |
62 | /* { |
63 | syscallarg(int) signum; |
64 | syscallarg(const netbsd32_sigactionp_t) nsa; |
65 | syscallarg(netbsd32_sigactionp_t) osa; |
66 | } */ |
67 | struct sigaction nsa, osa; |
68 | struct netbsd32_sigaction13 *sa32p, sa32; |
69 | int error; |
70 | |
71 | if (SCARG_P32(uap, nsa)) { |
72 | sa32p = SCARG_P32(uap, nsa); |
73 | if (copyin(sa32p, &sa32, sizeof(sa32))) |
74 | return EFAULT; |
75 | nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); |
76 | memset(&nsa.sa_mask, 0, sizeof(nsa.sa_mask)); |
77 | nsa.sa_mask.__bits[0] = sa32.netbsd32_sa_mask; |
78 | nsa.sa_flags = sa32.netbsd32_sa_flags; |
79 | } |
80 | error = sigaction1(l, SCARG(uap, signum), |
81 | SCARG_P32(uap, nsa) ? &nsa : 0, |
82 | SCARG_P32(uap, osa) ? &osa : 0, |
83 | NULL, 0); |
84 | |
85 | if (error) |
86 | return (error); |
87 | |
88 | if (SCARG_P32(uap, osa)) { |
89 | NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); |
90 | sa32.netbsd32_sa_mask = osa.sa_mask.__bits[0]; |
91 | sa32.netbsd32_sa_flags = osa.sa_flags; |
92 | sa32p = SCARG_P32(uap, osa); |
93 | if (copyout(&sa32, sa32p, sizeof(sa32))) |
94 | return EFAULT; |
95 | } |
96 | |
97 | return (0); |
98 | } |
99 | |
100 | int |
101 | netbsd32___sigaltstack14(struct lwp *l, const struct netbsd32___sigaltstack14_args *uap, register_t *retval) |
102 | { |
103 | /* { |
104 | syscallarg(const netbsd32_sigaltstackp_t) nss; |
105 | syscallarg(netbsd32_sigaltstackp_t) oss; |
106 | } */ |
107 | compat_sigaltstack(uap, netbsd32_sigaltstack, SS_ONSTACK, SS_DISABLE); |
108 | } |
109 | |
110 | /* ARGSUSED */ |
111 | int |
112 | netbsd32___sigaction14(struct lwp *l, const struct netbsd32___sigaction14_args *uap, register_t *retval) |
113 | { |
114 | /* { |
115 | syscallarg(int) signum; |
116 | syscallarg(const struct sigaction *) nsa; |
117 | syscallarg(struct sigaction *) osa; |
118 | } */ |
119 | struct netbsd32_sigaction sa32; |
120 | struct sigaction nsa, osa; |
121 | int error; |
122 | |
123 | if (SCARG_P32(uap, nsa)) { |
124 | error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32)); |
125 | if (error) |
126 | return (error); |
127 | nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler); |
128 | nsa.sa_mask = sa32.netbsd32_sa_mask; |
129 | nsa.sa_flags = sa32.netbsd32_sa_flags; |
130 | } |
131 | error = sigaction1(l, SCARG(uap, signum), |
132 | SCARG_P32(uap, nsa) ? &nsa : 0, |
133 | SCARG_P32(uap, osa) ? &osa : 0, |
134 | NULL, 0); |
135 | if (error) |
136 | return (error); |
137 | if (SCARG_P32(uap, osa)) { |
138 | NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); |
139 | sa32.netbsd32_sa_mask = osa.sa_mask; |
140 | sa32.netbsd32_sa_flags = osa.sa_flags; |
141 | error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32)); |
142 | if (error) |
143 | return (error); |
144 | } |
145 | return (0); |
146 | } |
147 | |
148 | /* ARGSUSED */ |
149 | int |
150 | netbsd32___sigaction_sigtramp(struct lwp *l, const struct netbsd32___sigaction_sigtramp_args *uap, register_t *retval) |
151 | { |
152 | /* { |
153 | syscallarg(int) signum; |
154 | syscallarg(const netbsd32_sigactionp_t) nsa; |
155 | syscallarg(netbsd32_sigactionp_t) osa; |
156 | syscallarg(netbsd32_voidp) tramp; |
157 | syscallarg(int) vers; |
158 | } */ |
159 | struct netbsd32_sigaction sa32; |
160 | struct sigaction nsa, osa; |
161 | int error; |
162 | |
163 | if (SCARG_P32(uap, nsa)) { |
164 | error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32)); |
165 | if (error) |
166 | return (error); |
167 | nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler); |
168 | nsa.sa_mask = sa32.netbsd32_sa_mask; |
169 | nsa.sa_flags = sa32.netbsd32_sa_flags; |
170 | } |
171 | error = sigaction1(l, SCARG(uap, signum), |
172 | SCARG_P32(uap, nsa) ? &nsa : 0, |
173 | SCARG_P32(uap, osa) ? &osa : 0, |
174 | SCARG_P32(uap, tramp), SCARG(uap, vers)); |
175 | if (error) |
176 | return (error); |
177 | if (SCARG_P32(uap, osa)) { |
178 | NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); |
179 | sa32.netbsd32_sa_mask = osa.sa_mask; |
180 | sa32.netbsd32_sa_flags = osa.sa_flags; |
181 | error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32)); |
182 | if (error) |
183 | return (error); |
184 | } |
185 | return (0); |
186 | } |
187 | |
188 | void |
189 | netbsd32_ksi32_to_ksi(struct _ksiginfo *si, const struct __ksiginfo32 *si32) |
190 | { |
191 | memset(si, 0, sizeof (*si)); |
192 | si->_signo = si32->_signo; |
193 | si->_code = si32->_code; |
194 | si->_errno = si32->_errno; |
195 | |
196 | switch (si32->_signo) { |
197 | case SIGILL: |
198 | case SIGBUS: |
199 | case SIGSEGV: |
200 | case SIGFPE: |
201 | case SIGTRAP: |
202 | si->_reason._fault._addr = |
203 | NETBSD32IPTR64(si32->_reason._fault._addr); |
204 | si->_reason._fault._trap = si32->_reason._fault._trap; |
205 | break; |
206 | case SIGALRM: |
207 | case SIGVTALRM: |
208 | case SIGPROF: |
209 | default: /* see sigqueue() and kill1() */ |
210 | si->_reason._rt._pid = si32->_reason._rt._pid; |
211 | si->_reason._rt._uid = si32->_reason._rt._uid; |
212 | si->_reason._rt._value.sival_int = |
213 | si32->_reason._rt._value.sival_int; |
214 | break; |
215 | case SIGCHLD: |
216 | si->_reason._child._pid = si32->_reason._child._pid; |
217 | si->_reason._child._uid = si32->_reason._child._uid; |
218 | si->_reason._child._utime = si32->_reason._child._utime; |
219 | si->_reason._child._stime = si32->_reason._child._stime; |
220 | break; |
221 | case SIGURG: |
222 | case SIGIO: |
223 | si->_reason._poll._band = si32->_reason._poll._band; |
224 | si->_reason._poll._fd = si32->_reason._poll._fd; |
225 | break; |
226 | } |
227 | } |
228 | |
229 | #ifdef KTRACE |
230 | static void |
231 | netbsd32_ksi_to_ksi32(struct __ksiginfo32 *si32, const struct _ksiginfo *si) |
232 | { |
233 | memset(si32, 0, sizeof (*si32)); |
234 | si32->_signo = si->_signo; |
235 | si32->_code = si->_code; |
236 | si32->_errno = si->_errno; |
237 | |
238 | switch (si->_signo) { |
239 | case SIGILL: |
240 | case SIGBUS: |
241 | case SIGSEGV: |
242 | case SIGFPE: |
243 | case SIGTRAP: |
244 | si32->_reason._fault._addr = |
245 | NETBSD32PTR32I(si->_reason._fault._addr); |
246 | si32->_reason._fault._trap = si->_reason._fault._trap; |
247 | break; |
248 | case SIGALRM: |
249 | case SIGVTALRM: |
250 | case SIGPROF: |
251 | default: /* see sigqueue() and kill1() */ |
252 | si32->_reason._rt._pid = si->_reason._rt._pid; |
253 | si32->_reason._rt._uid = si->_reason._rt._uid; |
254 | si32->_reason._rt._value.sival_int = |
255 | si->_reason._rt._value.sival_int; |
256 | break; |
257 | case SIGCHLD: |
258 | si32->_reason._child._pid = si->_reason._child._pid; |
259 | si32->_reason._child._uid = si->_reason._child._uid; |
260 | si32->_reason._child._utime = si->_reason._child._utime; |
261 | si32->_reason._child._stime = si->_reason._child._stime; |
262 | break; |
263 | case SIGURG: |
264 | case SIGIO: |
265 | si32->_reason._poll._band = si->_reason._poll._band; |
266 | si32->_reason._poll._fd = si->_reason._poll._fd; |
267 | break; |
268 | } |
269 | } |
270 | #endif |
271 | |
272 | void |
273 | netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si) |
274 | { |
275 | memset(si32, 0, sizeof (*si32)); |
276 | si32->si_signo = si->si_signo; |
277 | si32->si_code = si->si_code; |
278 | si32->si_errno = si->si_errno; |
279 | |
280 | switch (si32->si_signo) { |
281 | case 0: /* SA */ |
282 | si32->si_value.sival_int = si->si_value.sival_int; |
283 | break; |
284 | case SIGILL: |
285 | case SIGBUS: |
286 | case SIGSEGV: |
287 | case SIGFPE: |
288 | case SIGTRAP: |
289 | si32->si_addr = (uint32_t)(uintptr_t)si->si_addr; |
290 | si32->si_trap = si->si_trap; |
291 | break; |
292 | case SIGALRM: |
293 | case SIGVTALRM: |
294 | case SIGPROF: |
295 | default: |
296 | si32->si_pid = si->si_pid; |
297 | si32->si_uid = si->si_uid; |
298 | si32->si_value.sival_int = si->si_value.sival_int; |
299 | break; |
300 | case SIGCHLD: |
301 | si32->si_pid = si->si_pid; |
302 | si32->si_uid = si->si_uid; |
303 | si32->si_status = si->si_status; |
304 | si32->si_utime = si->si_utime; |
305 | si32->si_stime = si->si_stime; |
306 | break; |
307 | case SIGURG: |
308 | case SIGIO: |
309 | si32->si_band = si->si_band; |
310 | si32->si_fd = si->si_fd; |
311 | break; |
312 | } |
313 | } |
314 | |
315 | void |
316 | getucontext32(struct lwp *l, ucontext32_t *ucp) |
317 | { |
318 | struct proc *p = l->l_proc; |
319 | |
320 | KASSERT(mutex_owned(p->p_lock)); |
321 | |
322 | ucp->uc_flags = 0; |
323 | ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; |
324 | ucp->uc_sigmask = l->l_sigmask; |
325 | ucp->uc_flags |= _UC_SIGMASK; |
326 | |
327 | /* |
328 | * The (unsupplied) definition of the `current execution stack' |
329 | * in the System V Interface Definition appears to allow returning |
330 | * the main context stack. |
331 | */ |
332 | if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { |
333 | ucp->uc_stack.ss_sp = USRSTACK32; |
334 | ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); |
335 | ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ |
336 | } else { |
337 | /* Simply copy alternate signal execution stack. */ |
338 | ucp->uc_stack.ss_sp = |
339 | (uint32_t)(intptr_t)l->l_sigstk.ss_sp; |
340 | ucp->uc_stack.ss_size = l->l_sigstk.ss_size; |
341 | ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags; |
342 | } |
343 | ucp->uc_flags |= _UC_STACK; |
344 | mutex_exit(p->p_lock); |
345 | cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); |
346 | mutex_enter(p->p_lock); |
347 | } |
348 | |
349 | int |
350 | netbsd32_getcontext(struct lwp *l, const struct netbsd32_getcontext_args *uap, register_t *retval) |
351 | { |
352 | /* { |
353 | syscallarg(netbsd32_ucontextp) ucp; |
354 | } */ |
355 | struct proc *p = l->l_proc; |
356 | ucontext32_t uc; |
357 | |
358 | memset(&uc, 0, sizeof(uc)); |
359 | |
360 | mutex_enter(p->p_lock); |
361 | getucontext32(l, &uc); |
362 | mutex_exit(p->p_lock); |
363 | |
364 | return copyout(&uc, SCARG_P32(uap, ucp), sizeof (ucontext32_t)); |
365 | } |
366 | |
367 | int |
368 | setucontext32(struct lwp *l, const ucontext32_t *ucp) |
369 | { |
370 | struct proc *p = l->l_proc; |
371 | int error; |
372 | |
373 | KASSERT(mutex_owned(p->p_lock)); |
374 | |
375 | if ((ucp->uc_flags & _UC_SIGMASK) != 0) { |
376 | error = sigprocmask1(l, SIG_SETMASK, &ucp->uc_sigmask, NULL); |
377 | if (error != 0) |
378 | return error; |
379 | } |
380 | |
381 | mutex_exit(p->p_lock); |
382 | error = cpu_setmcontext32(l, &ucp->uc_mcontext, ucp->uc_flags); |
383 | mutex_enter(p->p_lock); |
384 | if (error != 0) |
385 | return (error); |
386 | |
387 | l->l_ctxlink = (void *)(intptr_t)ucp->uc_link; |
388 | |
389 | /* |
390 | * If there was stack information, update whether or not we are |
391 | * still running on an alternate signal stack. |
392 | */ |
393 | if ((ucp->uc_flags & _UC_STACK) != 0) { |
394 | if (ucp->uc_stack.ss_flags & SS_ONSTACK) |
395 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
396 | else |
397 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
398 | } |
399 | |
400 | return 0; |
401 | } |
402 | |
403 | /* ARGSUSED */ |
404 | int |
405 | netbsd32_setcontext(struct lwp *l, const struct netbsd32_setcontext_args *uap, register_t *retval) |
406 | { |
407 | /* { |
408 | syscallarg(netbsd32_ucontextp) ucp; |
409 | } */ |
410 | ucontext32_t uc; |
411 | int error; |
412 | struct proc *p = l->l_proc; |
413 | |
414 | error = copyin(SCARG_P32(uap, ucp), &uc, sizeof (uc)); |
415 | if (error) |
416 | return (error); |
417 | if (!(uc.uc_flags & _UC_CPU)) |
418 | return (EINVAL); |
419 | mutex_enter(p->p_lock); |
420 | error = setucontext32(l, &uc); |
421 | mutex_exit(p->p_lock); |
422 | if (error) |
423 | return (error); |
424 | |
425 | return (EJUSTRETURN); |
426 | } |
427 | |
428 | static int |
429 | netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size) |
430 | { |
431 | const siginfo_t *info = src; |
432 | siginfo32_t info32; |
433 | |
434 | netbsd32_si_to_si32(&info32, info); |
435 | |
436 | return copyout(&info32, dst, sizeof(info32)); |
437 | } |
438 | |
439 | static int |
440 | netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size) |
441 | { |
442 | struct timespec *ts = dst; |
443 | struct netbsd32_timespec ts32; |
444 | int error; |
445 | |
446 | error = copyin(src, &ts32, sizeof(ts32)); |
447 | if (error) |
448 | return error; |
449 | |
450 | netbsd32_to_timespec(&ts32, ts); |
451 | return 0; |
452 | } |
453 | |
454 | static int |
455 | netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size) |
456 | { |
457 | const struct timespec *ts = src; |
458 | struct netbsd32_timespec ts32; |
459 | |
460 | netbsd32_from_timespec(ts, &ts32); |
461 | |
462 | return copyout(&ts32, dst, sizeof(ts32)); |
463 | } |
464 | |
465 | int |
466 | netbsd32_____sigtimedwait50(struct lwp *l, const struct netbsd32_____sigtimedwait50_args *uap, register_t *retval) |
467 | { |
468 | /* { |
469 | syscallarg(netbsd32_sigsetp_t) set; |
470 | syscallarg(netbsd32_siginfop_t) info; |
471 | syscallarg(netbsd32_timespec50p_t) timeout; |
472 | } */ |
473 | struct sys_____sigtimedwait50_args ua; |
474 | |
475 | NETBSD32TOP_UAP(set, const sigset_t); |
476 | NETBSD32TOP_UAP(info, siginfo_t); |
477 | NETBSD32TOP_UAP(timeout, struct timespec); |
478 | |
479 | return sigtimedwait1(l, &ua, retval, |
480 | copyin, |
481 | netbsd32_sigtimedwait_put_info, |
482 | netbsd32_sigtimedwait_fetch_timeout, |
483 | netbsd32_sigtimedwait_put_timeout); |
484 | } |
485 | |
486 | int |
487 | netbsd32_sigqueueinfo(struct lwp *l, |
488 | const struct netbsd32_sigqueueinfo_args *uap, register_t *retval) |
489 | { |
490 | /* { |
491 | syscallarg(pid_t) pid; |
492 | syscallarg(const netbsd32_siginfop_t) info; |
493 | } */ |
494 | struct __ksiginfo32 ksi32; |
495 | ksiginfo_t ksi; |
496 | int error; |
497 | |
498 | if ((error = copyin(SCARG_P32(uap, info), &ksi32, |
499 | sizeof(ksi32))) != 0) |
500 | return error; |
501 | |
502 | KSI_INIT(&ksi); |
503 | netbsd32_ksi32_to_ksi(&ksi.ksi_info, &ksi32); |
504 | |
505 | return kill1(l, SCARG(uap, pid), &ksi, retval); |
506 | } |
507 | |
508 | struct netbsd32_ktr_psig { |
509 | int signo; |
510 | netbsd32_pointer_t action; |
511 | sigset_t mask; |
512 | int code; |
513 | /* and optional siginfo_t */ |
514 | }; |
515 | |
516 | #ifdef KTRACE |
517 | void |
518 | netbsd32_ktrpsig(int sig, sig_t action, const sigset_t *mask, |
519 | const ksiginfo_t *ksi) |
520 | { |
521 | struct ktrace_entry *kte; |
522 | lwp_t *l = curlwp; |
523 | struct { |
524 | struct netbsd32_ktr_psig kp; |
525 | siginfo32_t si; |
526 | } *kbuf; |
527 | |
528 | if (!KTRPOINT(l->l_proc, KTR_PSIG)) |
529 | return; |
530 | |
531 | if (ktealloc(&kte, (void *)&kbuf, l, KTR_PSIG, sizeof(*kbuf))) |
532 | return; |
533 | |
534 | kbuf->kp.signo = (char)sig; |
535 | NETBSD32PTR32(kbuf->kp.action, action); |
536 | kbuf->kp.mask = *mask; |
537 | |
538 | if (ksi) { |
539 | kbuf->kp.code = KSI_TRAPCODE(ksi); |
540 | (void)memset(&kbuf->si, 0, sizeof(kbuf->si)); |
541 | netbsd32_ksi_to_ksi32(&kbuf->si._info, &ksi->ksi_info); |
542 | ktesethdrlen(kte, sizeof(*kbuf)); |
543 | } else { |
544 | kbuf->kp.code = 0; |
545 | ktesethdrlen(kte, sizeof(struct netbsd32_ktr_psig)); |
546 | } |
547 | |
548 | ktraddentry(l, kte, KTA_WAITOK); |
549 | } |
550 | #endif |
551 | |
552 | |
553 | |