1 /* $OpenBSD: linux_signal.c,v 1.12 2003/02/25 09:10:27 tedu Exp $ */
2 /* $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $ */
3
4 /*
5 * Copyright (c) 1995 Frank van der Linden
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the NetBSD Project
19 * by Frank van der Linden
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/namei.h>
40 #include <sys/proc.h>
41 #include <sys/filedesc.h>
42 #include <sys/ioctl.h>
43 #include <sys/mount.h>
44 #include <sys/kernel.h>
45 #include <sys/signal.h>
46 #include <sys/signalvar.h>
47 #include <sys/malloc.h>
48
49 #include <sys/syscallargs.h>
50
51 #include <compat/linux/linux_types.h>
52 #include <compat/linux/linux_signal.h>
53 #include <compat/linux/linux_syscallargs.h>
54 #include <compat/linux/linux_util.h>
55
56 #define sigemptyset(s) bzero((s), sizeof(*(s)))
57 #define sigismember(s, n) (*(s) & sigmask(n))
58 #define sigaddset(s, n) (*(s) |= sigmask(n))
59
60 /* Locally used defines (in bsd<->linux conversion functions): */
61 #define linux_sigmask(n) (1 << ((n) - 1))
62 #define linux_sigemptyset(s) bzero((s), sizeof(*(s)))
63 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
64 & (1 << ((n) - 1) % LINUX__NSIG_BPW))
65 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
66 |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
67
68 int bsd_to_linux_sig[NSIG] = {
69 0,
70 LINUX_SIGHUP,
71 LINUX_SIGINT,
72 LINUX_SIGQUIT,
73 LINUX_SIGILL,
74 LINUX_SIGTRAP,
75 LINUX_SIGABRT,
76 LINUX_NSIG, /* XXX Kludge to get RT signal #32 to work */
77 LINUX_SIGFPE,
78 LINUX_SIGKILL,
79 LINUX_SIGBUS,
80 LINUX_SIGSEGV,
81 LINUX_NSIG + 1, /* XXX Kludge to get RT signal #32 to work */
82 LINUX_SIGPIPE,
83 LINUX_SIGALRM,
84 LINUX_SIGTERM,
85 LINUX_SIGURG,
86 LINUX_SIGSTOP,
87 LINUX_SIGTSTP,
88 LINUX_SIGCONT,
89 LINUX_SIGCHLD,
90 LINUX_SIGTTIN,
91 LINUX_SIGTTOU,
92 LINUX_SIGIO,
93 LINUX_SIGXCPU,
94 LINUX_SIGXFSZ,
95 LINUX_SIGVTALRM,
96 LINUX_SIGPROF,
97 LINUX_SIGWINCH,
98 0, /* SIGINFO */
99 LINUX_SIGUSR1,
100 LINUX_SIGUSR2,
101 };
102
103 int linux_to_bsd_sig[LINUX__NSIG] = {
104 0,
105 SIGHUP,
106 SIGINT,
107 SIGQUIT,
108 SIGILL,
109 SIGTRAP,
110 SIGABRT,
111 SIGBUS,
112 SIGFPE,
113 SIGKILL,
114 SIGUSR1,
115 SIGSEGV,
116 SIGUSR2,
117 SIGPIPE,
118 SIGALRM,
119 SIGTERM,
120 0, /* SIGSTKFLT */
121 SIGCHLD,
122 SIGCONT,
123 SIGSTOP,
124 SIGTSTP,
125 SIGTTIN,
126 SIGTTOU,
127 SIGURG,
128 SIGXCPU,
129 SIGXFSZ,
130 SIGVTALRM,
131 SIGPROF,
132 SIGWINCH,
133 SIGIO,
134 0, /* SIGUNUSED */
135 0,
136 SIGEMT, /* XXX Gruesome hack for linuxthreads: */
137 SIGSYS, /* Map 1st 2 RT signals onto ones we handle. */
138 0,
139 0,
140 0,
141 0,
142 0,
143 0,
144 0,
145 0,
146 0,
147 0,
148 0,
149 0,
150 0,
151 0,
152 0,
153 0,
154 0,
155 0,
156 0,
157 0,
158 0,
159 0,
160 0,
161 0,
162 0,
163 0,
164 0,
165 0,
166 0,
167 0,
168 };
169
170 /*
171 * Convert between Linux and BSD signal sets.
172 */
173 void
linux_old_to_bsd_sigset(lss,bss)174 linux_old_to_bsd_sigset(lss, bss)
175 const linux_old_sigset_t *lss;
176 sigset_t *bss;
177 {
178 linux_old_extra_to_bsd_sigset(lss, (const unsigned long *) 0, bss);
179 }
180
181 void
bsd_to_linux_old_sigset(bss,lss)182 bsd_to_linux_old_sigset(bss, lss)
183 const sigset_t *bss;
184 linux_old_sigset_t *lss;
185 {
186 bsd_to_linux_old_extra_sigset(bss, lss, (unsigned long *) 0);
187 }
188
189 void
linux_old_extra_to_bsd_sigset(lss,extra,bss)190 linux_old_extra_to_bsd_sigset(lss, extra, bss)
191 const linux_old_sigset_t *lss;
192 const unsigned long *extra;
193 sigset_t *bss;
194 {
195 linux_sigset_t lsnew;
196
197 /* convert old sigset to new sigset */
198 linux_sigemptyset(&lsnew);
199 lsnew.sig[0] = *lss;
200 if (extra)
201 bcopy(extra, &lsnew.sig[1],
202 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
203
204 linux_to_bsd_sigset(&lsnew, bss);
205 }
206
207 void
bsd_to_linux_old_extra_sigset(bss,lss,extra)208 bsd_to_linux_old_extra_sigset(bss, lss, extra)
209 const sigset_t *bss;
210 linux_old_sigset_t *lss;
211 unsigned long *extra;
212 {
213 linux_sigset_t lsnew;
214
215 bsd_to_linux_sigset(bss, &lsnew);
216
217 /* convert new sigset to old sigset */
218 *lss = lsnew.sig[0];
219 if (extra)
220 bcopy(&lsnew.sig[1], extra,
221 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
222 }
223
224 void
linux_to_bsd_sigset(lss,bss)225 linux_to_bsd_sigset(lss, bss)
226 const linux_sigset_t *lss;
227 sigset_t *bss;
228 {
229 int i, newsig;
230
231 sigemptyset(bss);
232 for (i = 1; i < LINUX__NSIG; i++) {
233 if (linux_sigismember(lss, i)) {
234 newsig = linux_to_bsd_sig[i];
235 if (newsig)
236 sigaddset(bss, newsig);
237 }
238 }
239 }
240
241 void
bsd_to_linux_sigset(bss,lss)242 bsd_to_linux_sigset(bss, lss)
243 const sigset_t *bss;
244 linux_sigset_t *lss;
245 {
246 int i, newsig;
247
248 linux_sigemptyset(lss);
249 for (i = 1; i < NSIG; i++) {
250 if (sigismember(bss, i)) {
251 newsig = bsd_to_linux_sig[i];
252 if (newsig)
253 linux_sigaddset(lss, newsig);
254 }
255 }
256 }
257
258 /*
259 * Convert between Linux and BSD sigaction structures. Linux has
260 * one extra field (sa_restorer) which we don't support.
261 */
262 void
linux_old_to_bsd_sigaction(lsa,bsa)263 linux_old_to_bsd_sigaction(lsa, bsa)
264 struct linux_old_sigaction *lsa;
265 struct sigaction *bsa;
266 {
267
268 bsa->sa_handler = lsa->sa__handler;
269 linux_old_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
270 bsa->sa_flags = 0;
271 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
272 bsa->sa_flags |= SA_ONSTACK;
273 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
274 bsa->sa_flags |= SA_RESTART;
275 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
276 bsa->sa_flags |= SA_RESETHAND;
277 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
278 bsa->sa_flags |= SA_NOCLDSTOP;
279 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
280 bsa->sa_flags |= SA_NODEFER;
281 }
282
283 void
bsd_to_linux_old_sigaction(bsa,lsa)284 bsd_to_linux_old_sigaction(bsa, lsa)
285 struct sigaction *bsa;
286 struct linux_old_sigaction *lsa;
287 {
288
289 lsa->sa__handler = bsa->sa_handler;
290 bsd_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
291 lsa->sa_flags = 0;
292 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
293 lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
294 if ((bsa->sa_flags & SA_ONSTACK) != 0)
295 lsa->sa_flags |= LINUX_SA_ONSTACK;
296 if ((bsa->sa_flags & SA_RESTART) != 0)
297 lsa->sa_flags |= LINUX_SA_RESTART;
298 if ((bsa->sa_flags & SA_NODEFER) != 0)
299 lsa->sa_flags |= LINUX_SA_NOMASK;
300 if ((bsa->sa_flags & SA_RESETHAND) != 0)
301 lsa->sa_flags |= LINUX_SA_ONESHOT;
302 lsa->sa_restorer = NULL;
303 }
304
305 void
linux_to_bsd_sigaction(lsa,bsa)306 linux_to_bsd_sigaction(lsa, bsa)
307 struct linux_sigaction *lsa;
308 struct sigaction *bsa;
309 {
310
311 bsa->sa_handler = lsa->sa__handler;
312 linux_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
313 bsa->sa_flags = 0;
314 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
315 bsa->sa_flags |= SA_NOCLDSTOP;
316 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
317 bsa->sa_flags |= SA_ONSTACK;
318 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
319 bsa->sa_flags |= SA_RESTART;
320 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
321 bsa->sa_flags |= SA_RESETHAND;
322 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
323 bsa->sa_flags |= SA_NODEFER;
324 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
325 bsa->sa_flags |= SA_SIGINFO;
326 }
327
328 void
bsd_to_linux_sigaction(bsa,lsa)329 bsd_to_linux_sigaction(bsa, lsa)
330 struct sigaction *bsa;
331 struct linux_sigaction *lsa;
332 {
333
334 /* Clear sa_flags and sa_restorer (if it exists) */
335 bzero(lsa, sizeof(struct linux_sigaction));
336
337 /* ...and fill in the mask and flags */
338 bsd_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
339 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
340 lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
341 if ((bsa->sa_flags & SA_ONSTACK) != 0)
342 lsa->sa_flags |= LINUX_SA_ONSTACK;
343 if ((bsa->sa_flags & SA_RESTART) != 0)
344 lsa->sa_flags |= LINUX_SA_RESTART;
345 if ((bsa->sa_flags & SA_NODEFER) != 0)
346 lsa->sa_flags |= LINUX_SA_NOMASK;
347 if ((bsa->sa_flags & SA_RESETHAND) != 0)
348 lsa->sa_flags |= LINUX_SA_ONESHOT;
349 if ((bsa->sa_flags & SA_SIGINFO) != 0)
350 lsa->sa_flags |= LINUX_SA_SIGINFO;
351 lsa->sa__handler = bsa->sa_handler;
352 }
353
354 int
linux_to_bsd_signal(int linuxsig,int * bsdsig)355 linux_to_bsd_signal(int linuxsig, int *bsdsig)
356 {
357 if (linuxsig < 0 || linuxsig >= LINUX__NSIG)
358 return (EINVAL);
359
360 *bsdsig = linux_to_bsd_sig[linuxsig];
361 return (0);
362 }
363
364 int
bsd_to_linux_signal(int bsdsig,int * linuxsig)365 bsd_to_linux_signal(int bsdsig, int *linuxsig)
366 {
367 if (bsdsig < 0 || bsdsig >= NSIG)
368 return (EINVAL);
369
370 *linuxsig = bsd_to_linux_sig[bsdsig];
371 return (0);
372 }
373
374 /*
375 * The Linux sigaction() system call. Do the usual conversions,
376 * and just call sigaction(). Some flags and values are silently
377 * ignored (see above).
378 */
379 int
linux_sys_sigaction(p,v,retval)380 linux_sys_sigaction(p, v, retval)
381 register struct proc *p;
382 void *v;
383 register_t *retval;
384 {
385 struct linux_sys_sigaction_args /* {
386 syscallarg(int) signum;
387 syscallarg(struct linux_old_sigaction *) nsa;
388 syscallarg(struct linux_old_sigaction *) osa;
389 } */ *uap = v;
390 struct linux_old_sigaction *nlsa, *olsa, tmplsa;
391 struct sigaction *nbsa, *obsa, tmpbsa;
392 struct sys_sigaction_args sa;
393 caddr_t sg;
394 int error;
395
396 if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
397 return (EINVAL);
398
399 sg = stackgap_init(p->p_emul);
400 nlsa = SCARG(uap, nsa);
401 olsa = SCARG(uap, osa);
402
403 if (olsa != NULL)
404 obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
405 else
406 obsa = NULL;
407
408 if (nlsa != NULL) {
409 nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
410 if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
411 return (error);
412 linux_old_to_bsd_sigaction(&tmplsa, &tmpbsa);
413 if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
414 return (error);
415 } else
416 nbsa = NULL;
417
418 SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
419 SCARG(&sa, nsa) = nbsa;
420 SCARG(&sa, osa) = obsa;
421
422 /* Silently ignore unknown signals */
423 if (SCARG(&sa, signum) == 0) {
424 if (obsa != NULL) {
425 obsa->sa_handler = SIG_IGN;
426 sigemptyset(&obsa->sa_mask);
427 obsa->sa_flags = 0;
428 }
429 }
430 else {
431 if ((error = sys_sigaction(p, &sa, retval)) != 0)
432 return (error);
433 }
434
435 if (olsa != NULL) {
436 if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
437 return (error);
438 bsd_to_linux_old_sigaction(&tmpbsa, &tmplsa);
439 if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
440 return (error);
441 }
442
443 return (0);
444 }
445
446 int
linux_sys_rt_sigaction(p,v,retval)447 linux_sys_rt_sigaction(p, v, retval)
448 register struct proc *p;
449 void *v;
450 register_t *retval;
451 {
452 struct linux_sys_rt_sigaction_args /* {
453 syscallarg(int) signum;
454 syscallarg(struct linux_sigaction *) nsa;
455 syscallarg(struct linux_sigaction *) osa;
456 syscallarg(size_t) sigsetsize;
457 } */ *uap = v;
458 struct linux_sigaction *nlsa, *olsa, tmplsa;
459 struct sigaction *nbsa, *obsa, tmpbsa;
460 struct sys_sigaction_args sa;
461 caddr_t sg;
462 int error;
463
464 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
465 return (EINVAL);
466
467 if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
468 return (EINVAL);
469
470 sg = stackgap_init(p->p_emul);
471 nlsa = SCARG(uap, nsa);
472 olsa = SCARG(uap, osa);
473
474 if (olsa != NULL)
475 obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
476 else
477 obsa = NULL;
478
479 if (nlsa != NULL) {
480 nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
481 if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
482 return (error);
483 linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
484 if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
485 return (error);
486 }
487 else
488 nbsa = NULL;
489
490 SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
491 SCARG(&sa, nsa) = nbsa;
492 SCARG(&sa, osa) = obsa;
493
494 /* Silently ignore unknown signals */
495 if (SCARG(&sa, signum) == 0) {
496 if (obsa != NULL) {
497 obsa->sa_handler = SIG_IGN;
498 sigemptyset(&obsa->sa_mask);
499 obsa->sa_flags = 0;
500 }
501 }
502 else {
503 if ((error = sys_sigaction(p, &sa, retval)) != 0)
504 return (error);
505 }
506
507 if (olsa != NULL) {
508 if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
509 return (error);
510 bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
511 if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
512 return (error);
513 }
514
515 return (0);
516 }
517
518 /*
519 * The Linux signal() system call. I think that the signal() in the C
520 * library actually calls sigaction, so I doubt this one is ever used.
521 * But hey, it can't hurt having it here. The same restrictions as for
522 * sigaction() apply.
523 */
524 int
linux_sys_signal(p,v,retval)525 linux_sys_signal(p, v, retval)
526 register struct proc *p;
527 void *v;
528 register_t *retval;
529 {
530 struct linux_sys_signal_args /* {
531 syscallarg(int) sig;
532 syscallarg(linux_handler_t) handler;
533 } */ *uap = v;
534 caddr_t sg;
535 struct sys_sigaction_args sa_args;
536 struct sigaction *osa, *nsa, tmpsa;
537 int error;
538
539 if (SCARG(uap, sig) < 0 || SCARG(uap, sig) >= LINUX__NSIG)
540 return (EINVAL);
541
542 sg = stackgap_init(p->p_emul);
543 nsa = stackgap_alloc(&sg, sizeof *nsa);
544 osa = stackgap_alloc(&sg, sizeof *osa);
545
546 tmpsa.sa_handler = SCARG(uap, handler);
547 tmpsa.sa_mask = (sigset_t) 0;
548 tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
549 if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
550 return (error);
551
552 SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
553 SCARG(&sa_args, osa) = osa;
554 SCARG(&sa_args, nsa) = nsa;
555
556 /* Silently ignore unknown signals */
557 if (SCARG(&sa_args, signum) != 0) {
558 if ((error = sys_sigaction(p, &sa_args, retval)))
559 return (error);
560 }
561
562 if ((error = copyin(osa, &tmpsa, sizeof *osa)))
563 return (error);
564 retval[0] = (register_t) tmpsa.sa_handler;
565
566 return (0);
567 }
568
569 /*
570 * This is just a copy of the svr4 compat one. I feel so creative now.
571 */
572 int
linux_sys_sigprocmask(p,v,retval)573 linux_sys_sigprocmask(p, v, retval)
574 register struct proc *p;
575 void *v;
576 register_t *retval;
577 {
578 struct linux_sys_sigprocmask_args /* {
579 syscallarg(int) how;
580 syscallarg(linux_old_sigset_t *) set;
581 syscallarg(linux_old_sigset_t *) oset;
582 } */ *uap = v;
583 linux_old_sigset_t ss;
584 sigset_t bs;
585 int error = 0;
586
587 *retval = 0;
588
589 if (SCARG(uap, oset) != NULL) {
590 /* Fix the return value first if needed */
591 bsd_to_linux_old_sigset(&p->p_sigmask, &ss);
592 if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
593 return (error);
594 }
595
596 if (SCARG(uap, set) == NULL)
597 /* Just examine */
598 return (0);
599
600 if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
601 return (error);
602
603 linux_old_to_bsd_sigset(&ss, &bs);
604
605 (void) splhigh();
606
607 switch (SCARG(uap, how)) {
608 case LINUX_SIG_BLOCK:
609 p->p_sigmask |= bs & ~sigcantmask;
610 break;
611
612 case LINUX_SIG_UNBLOCK:
613 p->p_sigmask &= ~bs;
614 break;
615
616 case LINUX_SIG_SETMASK:
617 p->p_sigmask = bs & ~sigcantmask;
618 break;
619
620 default:
621 error = EINVAL;
622 break;
623 }
624
625 (void) spl0();
626
627 return (error);
628 }
629
630 int
linux_sys_rt_sigprocmask(p,v,retval)631 linux_sys_rt_sigprocmask(p, v, retval)
632 register struct proc *p;
633 void *v;
634 register_t *retval;
635 {
636 struct linux_sys_rt_sigprocmask_args /* {
637 syscallarg(int) how;
638 syscallarg(const linux_sigset_t *) set;
639 syscallarg(linux_sigset_t *) oset;
640 syscallarg(size_t) sigsetsize;
641 } */ *uap = v;
642 linux_sigset_t ls;
643 sigset_t bs;
644 int error = 0;
645
646 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
647 return (EINVAL);
648
649 *retval = 0;
650
651 if (SCARG(uap, oset) != NULL) {
652 /* Fix the return value first if needed */
653 bsd_to_linux_sigset(&p->p_sigmask, &ls);
654 if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
655 return (error);
656 }
657
658 if (SCARG(uap, set) == NULL)
659 /* Just examine */
660 return (0);
661
662 if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
663 return (error);
664
665 linux_to_bsd_sigset(&ls, &bs);
666
667 (void) splhigh();
668
669 switch (SCARG(uap, how)) {
670 case LINUX_SIG_BLOCK:
671 p->p_sigmask |= bs & ~sigcantmask;
672 break;
673
674 case LINUX_SIG_UNBLOCK:
675 p->p_sigmask &= ~bs;
676 break;
677
678 case LINUX_SIG_SETMASK:
679 p->p_sigmask = bs & ~sigcantmask;
680 break;
681
682 default:
683 error = EINVAL;
684 break;
685 }
686
687 (void) spl0();
688
689 return (error);
690 }
691
692 /*
693 * The functions below really make no distinction between an int
694 * and [linux_]sigset_t. This is ok for now, but it might break
695 * sometime. Then again, sigset_t is trusted to be an int everywhere
696 * else in the kernel too.
697 */
698 /* ARGSUSED */
699 int
linux_sys_siggetmask(p,v,retval)700 linux_sys_siggetmask(p, v, retval)
701 register struct proc *p;
702 void *v;
703 register_t *retval;
704 {
705
706 bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
707 return (0);
708 }
709
710 /*
711 * The following three functions fiddle with a process' signal mask.
712 * Convert the signal masks because of the different signal
713 * values for Linux. The need for this is the reason why
714 * they are here, and have not been mapped directly.
715 */
716 int
linux_sys_sigsetmask(p,v,retval)717 linux_sys_sigsetmask(p, v, retval)
718 register struct proc *p;
719 void *v;
720 register_t *retval;
721 {
722 struct linux_sys_sigsetmask_args /* {
723 syscallarg(linux_old_sigset_t) mask;
724 } */ *uap = v;
725 linux_old_sigset_t mask;
726 sigset_t bsdsig;
727
728 bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
729
730 mask = SCARG(uap, mask);
731 bsd_to_linux_old_sigset(&bsdsig, &mask);
732
733 splhigh();
734 p->p_sigmask = bsdsig & ~sigcantmask;
735 spl0();
736
737 return (0);
738 }
739
740 int
linux_sys_sigpending(p,v,retval)741 linux_sys_sigpending(p, v, retval)
742 register struct proc *p;
743 void *v;
744 register_t *retval;
745 {
746 struct linux_sys_sigpending_args /* {
747 syscallarg(linux_old_sigset_t *) mask;
748 } */ *uap = v;
749 sigset_t bs;
750 linux_old_sigset_t ls;
751
752 bs = p->p_siglist & p->p_sigmask;
753 bsd_to_linux_old_sigset(&bs, &ls);
754
755 return (copyout(&ls, SCARG(uap, mask), sizeof ls));
756 }
757
758 int
linux_sys_rt_sigpending(p,v,retval)759 linux_sys_rt_sigpending(p, v, retval)
760 register struct proc *p;
761 void *v;
762 register_t *retval;
763 {
764 struct linux_sys_rt_sigpending_args /* {
765 syscallarg(linux_sigset_t *) set;
766 syscallarg(size_t) sigsetsize;
767 } */ *uap = v;
768 sigset_t bs;
769 linux_sigset_t ls;
770
771 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
772 return (EINVAL);
773
774 bs = p->p_siglist & p->p_sigmask;
775 bsd_to_linux_sigset(&bs, &ls);
776
777 return (copyout(&ls, SCARG(uap, set), sizeof ls));
778 }
779
780 int
linux_sys_sigsuspend(p,v,retval)781 linux_sys_sigsuspend(p, v, retval)
782 register struct proc *p;
783 void *v;
784 register_t *retval;
785 {
786 struct linux_sys_sigsuspend_args /* {
787 syscallarg(caddr_t) restart;
788 syscallarg(int) oldmask;
789 syscallarg(int) mask;
790 } */ *uap = v;
791 struct sys_sigsuspend_args sa;
792 linux_old_sigset_t mask = SCARG(uap, mask);
793
794 linux_old_to_bsd_sigset(&mask, &SCARG(&sa, mask));
795 return (sys_sigsuspend(p, &sa, retval));
796 }
797
798 int
linux_sys_rt_sigsuspend(p,v,retval)799 linux_sys_rt_sigsuspend(p, v, retval)
800 register struct proc *p;
801 void *v;
802 register_t *retval;
803 {
804 struct linux_sys_rt_sigsuspend_args /* {
805 syscallarg(sigset_t *) unewset;
806 syscallarg(size_t) sigsetsize;
807 } */ *uap = v;
808 struct sys_sigsuspend_args sa;
809 linux_sigset_t mask;
810 int error;
811
812 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
813 return (EINVAL);
814
815 error = copyin(SCARG(uap, unewset), &mask, sizeof mask);
816 if (error)
817 return (error);
818
819 linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
820 return (sys_sigsuspend(p, &sa, retval));
821 }
822
823 /*
824 * Linux' sigaltstack structure is just of a different order than BSD's
825 * so just shuffle the fields around and call our version.
826 */
827 int
linux_sys_sigaltstack(p,v,retval)828 linux_sys_sigaltstack(p, v, retval)
829 register struct proc *p;
830 void *v;
831 register_t *retval;
832 {
833 struct linux_sys_sigaltstack_args /* {
834 syscallarg(const struct linux_sigaltstack *) nss;
835 syscallarg(struct linux_sigaltstack *) oss;
836 } */ *uap = v;
837 struct linux_sigaltstack linux_ss;
838 struct sigaltstack *bsd_nss, *bsd_oss;
839 struct sys_sigaltstack_args sa;
840 int error;
841 caddr_t sg;
842
843 sg = stackgap_init(p->p_emul);
844
845 if (SCARG(uap, nss) != NULL) {
846 bsd_nss = stackgap_alloc(&sg, sizeof *bsd_nss);
847
848 error = copyin(SCARG(uap, nss), &linux_ss, sizeof linux_ss);
849 if (error)
850 return (error);
851
852 bsd_nss->ss_sp = linux_ss.ss_sp;
853 bsd_nss->ss_size = linux_ss.ss_size;
854 bsd_nss->ss_flags = (linux_ss.ss_flags & LINUX_SS_DISABLE) ?
855 SS_DISABLE : 0;
856
857 SCARG(&sa, nss) = bsd_nss;
858 } else
859 SCARG(&sa, nss) = NULL;
860
861 if (SCARG(uap, oss) == NULL) {
862 SCARG(&sa, oss) = NULL;
863 return (sys_sigaltstack(p, &sa, retval));
864 }
865 SCARG(&sa, oss) = bsd_oss = stackgap_alloc(&sg, sizeof *bsd_oss);
866
867 error = sys_sigaltstack(p, &sa, retval);
868 if (error)
869 return (error);
870
871 linux_ss.ss_sp = bsd_oss->ss_sp;
872 linux_ss.ss_size = bsd_oss->ss_size;
873 linux_ss.ss_flags = 0;
874 if (bsd_oss->ss_flags & SS_ONSTACK)
875 linux_ss.ss_flags |= LINUX_SS_ONSTACK;
876 if (bsd_oss->ss_flags & SS_DISABLE)
877 linux_ss.ss_flags |= LINUX_SS_DISABLE;
878 return (copyout(&linux_ss, SCARG(uap, oss), sizeof linux_ss));
879 }
880
881 /*
882 * The deprecated pause(2), which is really just an instance
883 * of sigsuspend(2).
884 */
885 int
linux_sys_pause(p,v,retval)886 linux_sys_pause(p, v, retval)
887 register struct proc *p;
888 void *v;
889 register_t *retval;
890 {
891 struct sys_sigsuspend_args bsa;
892
893 SCARG(&bsa, mask) = p->p_sigmask;
894 return (sys_sigsuspend(p, &bsa, retval));
895 }
896
897 /*
898 * Once more: only a signal conversion is needed.
899 */
900 int
linux_sys_kill(p,v,retval)901 linux_sys_kill(p, v, retval)
902 register struct proc *p;
903 void *v;
904 register_t *retval;
905 {
906 struct linux_sys_kill_args /* {
907 syscallarg(int) pid;
908 syscallarg(int) signum;
909 } */ *uap = v;
910 struct sys_kill_args ka;
911
912 SCARG(&ka, pid) = SCARG(uap, pid);
913 if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
914 return (EINVAL);
915 SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
916 return (sys_kill(p, &ka, retval));
917 }
918