linux_signal.c revision 1.31.2.3 1 /* $NetBSD: linux_signal.c,v 1.31.2.3 2002/02/28 04:12:57 nathanw Exp $ */
2 /*-
3 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Frank van der Linden and Eric Haszlakiewicz.
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 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37 /*
38 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
39 */
40
41 /*
42 * Functions in multiarch:
43 * linux_sys_signal : linux_sig_notalpha.c
44 * linux_sys_siggetmask : linux_sig_notalpha.c
45 * linux_sys_sigsetmask : linux_sig_notalpha.c
46 * linux_sys_pause : linux_sig_notalpha.c
47 * linux_sys_sigaction : linux_sigaction.c
48 *
49 */
50
51 /*
52 * Unimplemented:
53 * linux_sys_rt_sigtimedwait : sigsuspend w/timeout.
54 */
55
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.31.2.3 2002/02/28 04:12:57 nathanw Exp $");
58
59 #define COMPAT_LINUX 1
60
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/namei.h>
64 #include <sys/lwp.h>
65 #include <sys/proc.h>
66 #include <sys/filedesc.h>
67 #include <sys/ioctl.h>
68 #include <sys/mount.h>
69 #include <sys/kernel.h>
70 #include <sys/signal.h>
71 #include <sys/signalvar.h>
72 #include <sys/malloc.h>
73
74 #include <sys/syscallargs.h>
75
76 #include <compat/linux/common/linux_types.h>
77 #include <compat/linux/common/linux_signal.h>
78 #include <compat/linux/common/linux_siginfo.h>
79 #include <compat/linux/common/linux_util.h>
80
81 #include <compat/linux/linux_syscallargs.h>
82
83 /* Locally used defines (in bsd<->linux conversion functions): */
84 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s)))
85 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
86 & (1 << ((n) - 1) % LINUX__NSIG_BPW))
87 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
88 |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
89
90 /* Note: linux_to_native_sig[] is in <arch>/linux_sigarray.c */
91 const int native_to_linux_sig[NSIG] = {
92 0,
93 LINUX_SIGHUP,
94 LINUX_SIGINT,
95 LINUX_SIGQUIT,
96 LINUX_SIGILL,
97 LINUX_SIGTRAP,
98 LINUX_SIGABRT,
99 0, /* SIGEMT */
100 LINUX_SIGFPE,
101 LINUX_SIGKILL,
102 LINUX_SIGBUS,
103 LINUX_SIGSEGV,
104 0, /* SIGSYS */
105 LINUX_SIGPIPE,
106 LINUX_SIGALRM,
107 LINUX_SIGTERM,
108 LINUX_SIGURG,
109 LINUX_SIGSTOP,
110 LINUX_SIGTSTP,
111 LINUX_SIGCONT,
112 LINUX_SIGCHLD,
113 LINUX_SIGTTIN,
114 LINUX_SIGTTOU,
115 LINUX_SIGIO,
116 LINUX_SIGXCPU,
117 LINUX_SIGXFSZ,
118 LINUX_SIGVTALRM,
119 LINUX_SIGPROF,
120 LINUX_SIGWINCH,
121 0, /* SIGINFO */
122 LINUX_SIGUSR1,
123 LINUX_SIGUSR2,
124 LINUX_SIGPWR,
125 };
126
127 /*
128 * Convert between Linux and BSD signal sets.
129 */
130 #if LINUX__NSIG_WORDS > 1
131 void
132 linux_old_extra_to_native_sigset(bss, lss, extra)
133 sigset_t *bss;
134 const linux_old_sigset_t *lss;
135 const unsigned long *extra;
136 {
137 linux_sigset_t lsnew;
138
139 /* convert old sigset to new sigset */
140 linux_sigemptyset(&lsnew);
141 lsnew.sig[0] = *lss;
142 if (extra)
143 memcpy(&lsnew.sig[1], extra,
144 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
145
146 linux_to_native_sigset(bss, &lsnew);
147 }
148
149 void
150 native_to_linux_old_extra_sigset(lss, extra, bss)
151 linux_old_sigset_t *lss;
152 unsigned long *extra;
153 const sigset_t *bss;
154 {
155 linux_sigset_t lsnew;
156
157 native_to_linux_sigset(&lsnew, bss);
158
159 /* convert new sigset to old sigset */
160 *lss = lsnew.sig[0];
161 if (extra)
162 memcpy(extra, &lsnew.sig[1],
163 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
164 }
165 #endif
166
167 void
168 linux_to_native_sigset(bss, lss)
169 sigset_t *bss;
170 const linux_sigset_t *lss;
171 {
172 int i, newsig;
173
174 sigemptyset(bss);
175 for (i = 1; i < LINUX__NSIG; i++) {
176 if (linux_sigismember(lss, i)) {
177 newsig = linux_to_native_sig[i];
178 if (newsig)
179 sigaddset(bss, newsig);
180 }
181 }
182 }
183
184 void
185 native_to_linux_sigset(lss, bss)
186 linux_sigset_t *lss;
187 const sigset_t *bss;
188 {
189 int i, newsig;
190
191 linux_sigemptyset(lss);
192 for (i = 1; i < NSIG; i++) {
193 if (sigismember(bss, i)) {
194 newsig = native_to_linux_sig[i];
195 if (newsig)
196 linux_sigaddset(lss, newsig);
197 }
198 }
199 }
200
201 unsigned int
202 native_to_linux_sigflags(bsf)
203 const int bsf;
204 {
205 unsigned int lsf = 0;
206 if ((bsf & SA_NOCLDSTOP) != 0)
207 lsf |= LINUX_SA_NOCLDSTOP;
208 if ((bsf & SA_NOCLDWAIT) != 0)
209 lsf |= LINUX_SA_NOCLDWAIT;
210 if ((bsf & SA_ONSTACK) != 0)
211 lsf |= LINUX_SA_ONSTACK;
212 if ((bsf & SA_RESTART) != 0)
213 lsf |= LINUX_SA_RESTART;
214 if ((bsf & SA_NODEFER) != 0)
215 lsf |= LINUX_SA_NOMASK;
216 if ((bsf & SA_RESETHAND) != 0)
217 lsf |= LINUX_SA_ONESHOT;
218 if ((bsf & SA_SIGINFO) != 0)
219 lsf |= LINUX_SA_SIGINFO;
220 return lsf;
221 }
222
223 int
224 linux_to_native_sigflags(lsf)
225 const unsigned long lsf;
226 {
227 int bsf = 0;
228 if ((lsf & LINUX_SA_NOCLDSTOP) != 0)
229 bsf |= SA_NOCLDSTOP;
230 if ((lsf & LINUX_SA_NOCLDWAIT) != 0)
231 bsf |= SA_NOCLDWAIT;
232 if ((lsf & LINUX_SA_ONSTACK) != 0)
233 bsf |= SA_ONSTACK;
234 if ((lsf & LINUX_SA_RESTART) != 0)
235 bsf |= SA_RESTART;
236 if ((lsf & LINUX_SA_ONESHOT) != 0)
237 bsf |= SA_RESETHAND;
238 if ((lsf & LINUX_SA_NOMASK) != 0)
239 bsf |= SA_NODEFER;
240 if ((lsf & LINUX_SA_SIGINFO) != 0)
241 bsf |= SA_SIGINFO;
242 #ifdef DEBUG_LINUX
243 if ((lsf & ~LINUX_SA_ALLBITS) != 0)
244 uprintf(
245 "linux_old_to_native_sigflags: %lx extra bits ignored\n",
246 lsf);
247 #endif
248 return bsf;
249 }
250
251 /*
252 * Convert between Linux and BSD sigaction structures. Linux sometimes
253 * has one extra field (sa_restorer) which we don't support.
254 */
255 void
256 linux_old_to_native_sigaction(bsa, lsa)
257 struct sigaction *bsa;
258 const struct linux_old_sigaction *lsa;
259 {
260 bsa->sa_handler = lsa->sa_handler;
261 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->sa_mask);
262 bsa->sa_flags = linux_to_native_sigflags(lsa->sa_flags);
263 #ifndef __alpha__
264 /*
265 * XXX: On the alpha sa_restorer is elsewhere.
266 */
267 #ifdef DEBUG_LINUX
268 if (lsa->sa_restorer != NULL)
269 uprintf("linux_old_to_native_sigaction: sa_restorer ignored\n");
270 #endif
271 #endif
272 }
273
274 void
275 native_to_linux_old_sigaction(lsa, bsa)
276 struct linux_old_sigaction *lsa;
277 const struct sigaction *bsa;
278 {
279 lsa->sa_handler = bsa->sa_handler;
280 native_to_linux_old_sigset(&lsa->sa_mask, &bsa->sa_mask);
281 lsa->sa_flags = native_to_linux_sigflags(bsa->sa_flags);
282 #ifndef __alpha__
283 lsa->sa_restorer = NULL;
284 #endif
285 }
286
287 /* ...and the new sigaction conversion funcs. */
288 void
289 linux_to_native_sigaction(bsa, lsa)
290 struct sigaction *bsa;
291 const struct linux_sigaction *lsa;
292 {
293 bsa->sa_handler = lsa->sa_handler;
294 linux_to_native_sigset(&bsa->sa_mask, &lsa->sa_mask);
295 bsa->sa_flags = linux_to_native_sigflags(lsa->sa_flags);
296 #ifndef __alpha__
297 #ifdef DEBUG_LINUX
298 if (lsa->sa_restorer != 0)
299 uprintf("linux_to_native_sigaction: sa_restorer ignored\n");
300 #endif
301 #endif
302 }
303
304 void
305 native_to_linux_sigaction(lsa, bsa)
306 struct linux_sigaction *lsa;
307 const struct sigaction *bsa;
308 {
309 lsa->sa_handler = bsa->sa_handler;
310 native_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask);
311 lsa->sa_flags = native_to_linux_sigflags(bsa->sa_flags);
312 #ifndef __alpha__
313 lsa->sa_restorer = NULL;
314 #endif
315 }
316
317 /* ----------------------------------------------------------------------- */
318
319 /*
320 * The Linux sigaction() system call. Do the usual conversions,
321 * and just call sigaction(). Some flags and values are silently
322 * ignored (see above).
323 */
324 int
325 linux_sys_rt_sigaction(l, v, retval)
326 struct lwp *l;
327 void *v;
328 register_t *retval;
329 {
330 struct linux_sys_rt_sigaction_args /* {
331 syscallarg(int) signum;
332 syscallarg(const struct linux_sigaction *) nsa;
333 syscallarg(struct linux_sigaction *) osa;
334 syscallarg(size_t) sigsetsize;
335 } */ *uap = v;
336 struct proc *p = l->l_proc;
337 struct linux_sigaction nlsa, olsa;
338 struct sigaction nbsa, obsa;
339 int error, sig;
340
341 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
342 return (EINVAL);
343
344 if (SCARG(uap, nsa)) {
345 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
346 if (error)
347 return (error);
348 linux_to_native_sigaction(&nbsa, &nlsa);
349 }
350 sig = SCARG(uap, signum);
351 if (sig < 0 || sig >= LINUX__NSIG)
352 return (EINVAL);
353 if (sig > 0 && !linux_to_native_sig[sig]) {
354 /* Pretend that we did something useful for unknown signals. */
355 obsa.sa_handler = SIG_IGN;
356 sigemptyset(&obsa.sa_mask);
357 obsa.sa_flags = 0;
358 } else {
359 error = sigaction1(p, linux_to_native_sig[sig],
360 SCARG(uap, nsa) ? &nbsa : NULL, SCARG(uap, osa) ? &obsa : NULL);
361 if (error)
362 return (error);
363 }
364 if (SCARG(uap, osa)) {
365 native_to_linux_sigaction(&olsa, &obsa);
366 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
367 if (error)
368 return (error);
369 }
370 return (0);
371 }
372
373 int
374 linux_sigprocmask1(p, how, set, oset)
375 struct proc *p;
376 int how;
377 const linux_old_sigset_t *set;
378 linux_old_sigset_t *oset;
379 {
380 linux_old_sigset_t nlss, olss;
381 sigset_t nbss, obss;
382 int error;
383
384 switch (how) {
385 case LINUX_SIG_BLOCK:
386 how = SIG_BLOCK;
387 break;
388 case LINUX_SIG_UNBLOCK:
389 how = SIG_UNBLOCK;
390 break;
391 case LINUX_SIG_SETMASK:
392 how = SIG_SETMASK;
393 break;
394 default:
395 return (EINVAL);
396 }
397
398 if (set) {
399 error = copyin(set, &nlss, sizeof(nlss));
400 if (error)
401 return (error);
402 linux_old_to_native_sigset(&nbss, &nlss);
403 }
404 error = sigprocmask1(p, how,
405 set ? &nbss : NULL, oset ? &obss : NULL);
406 if (error)
407 return (error);
408 if (oset) {
409 native_to_linux_old_sigset(&olss, &obss);
410 error = copyout(&olss, oset, sizeof(olss));
411 if (error)
412 return (error);
413 }
414 return (error);
415 }
416
417 int
418 linux_sys_rt_sigprocmask(l, v, retval)
419 struct lwp *l;
420 void *v;
421 register_t *retval;
422 {
423 struct linux_sys_rt_sigprocmask_args /* {
424 syscallarg(int) how;
425 syscallarg(const linux_sigset_t *) set;
426 syscallarg(linux_sigset_t *) oset;
427 syscallarg(size_t) sigsetsize;
428 } */ *uap = v;
429 struct proc *p = l->l_proc;
430 linux_sigset_t nlss, olss, *oset;
431 const linux_sigset_t *set;
432 sigset_t nbss, obss;
433 int error, how;
434
435 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
436 return (EINVAL);
437
438 switch (SCARG(uap, how)) {
439 case LINUX_SIG_BLOCK:
440 how = SIG_BLOCK;
441 break;
442 case LINUX_SIG_UNBLOCK:
443 how = SIG_UNBLOCK;
444 break;
445 case LINUX_SIG_SETMASK:
446 how = SIG_SETMASK;
447 break;
448 default:
449 return (EINVAL);
450 }
451
452 set = SCARG(uap, set);
453 oset = SCARG(uap, oset);
454
455 if (set) {
456 error = copyin(set, &nlss, sizeof(nlss));
457 if (error)
458 return (error);
459 linux_to_native_sigset(&nbss, &nlss);
460 }
461 error = sigprocmask1(p, how,
462 set ? &nbss : NULL, oset ? &obss : NULL);
463 if (!error && oset) {
464 native_to_linux_sigset(&olss, &obss);
465 error = copyout(&olss, oset, sizeof(olss));
466 }
467 return (error);
468 }
469
470 int
471 linux_sys_rt_sigpending(l, v, retval)
472 struct lwp *l;
473 void *v;
474 register_t *retval;
475 {
476 struct linux_sys_rt_sigpending_args /* {
477 syscallarg(linux_sigset_t *) set;
478 syscallarg(size_t) sigsetsize;
479 } */ *uap = v;
480 struct proc *p = l->l_proc;
481 sigset_t bss;
482 linux_sigset_t lss;
483
484 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
485 return (EINVAL);
486
487 sigpending1(p, &bss);
488 native_to_linux_sigset(&lss, &bss);
489 return copyout(&lss, SCARG(uap, set), sizeof(lss));
490 }
491
492 int
493 linux_sys_sigpending(l, v, retval)
494 struct lwp *l;
495 void *v;
496 register_t *retval;
497 {
498 struct linux_sys_sigpending_args /* {
499 syscallarg(linux_old_sigset_t *) mask;
500 } */ *uap = v;
501 struct proc *p = l->l_proc;
502 sigset_t bss;
503 linux_old_sigset_t lss;
504
505 sigpending1(p, &bss);
506 native_to_linux_old_sigset(&lss, &bss);
507 return copyout(&lss, SCARG(uap, set), sizeof(lss));
508 }
509
510 int
511 linux_sys_sigsuspend(l, v, retval)
512 struct lwp *l;
513 void *v;
514 register_t *retval;
515 {
516 struct linux_sys_sigsuspend_args /* {
517 syscallarg(caddr_t) restart;
518 syscallarg(int) oldmask;
519 syscallarg(int) mask;
520 } */ *uap = v;
521 struct proc *p = l->l_proc;
522 linux_old_sigset_t lss;
523 sigset_t bss;
524
525 lss = SCARG(uap, mask);
526 linux_old_to_native_sigset(&bss, &lss);
527 return (sigsuspend1(p, &bss));
528 }
529 int
530 linux_sys_rt_sigsuspend(l, v, retval)
531 struct lwp *l;
532 void *v;
533 register_t *retval;
534 {
535 struct linux_sys_rt_sigsuspend_args /* {
536 syscallarg(linux_sigset_t *) unewset;
537 syscallarg(size_t) sigsetsize;
538 } */ *uap = v;
539 struct proc *p = l->l_proc;
540 linux_sigset_t lss;
541 sigset_t bss;
542 int error;
543
544 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
545 return (EINVAL);
546
547 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t));
548 if (error)
549 return (error);
550
551 linux_to_native_sigset(&bss, &lss);
552
553 return (sigsuspend1(p, &bss));
554 }
555
556 /*
557 * Once more: only a signal conversion is needed.
558 * Note: also used as sys_rt_queueinfo. The info field is ignored.
559 */
560 int
561 linux_sys_rt_queueinfo(l, v, retval)
562 struct lwp *l;
563 void *v;
564 register_t *retval;
565 {
566 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */
567 #if 0
568 struct linux_sys_rt_queueinfo_args /* {
569 syscallarg(int) pid;
570 syscallarg(int) signum;
571 syscallarg(siginfo_t *) uinfo;
572 } */ *uap = v;
573 #endif
574
575 /* XXX To really implement this we need to */
576 /* XXX keep a list of queued signals somewhere. */
577 return (linux_sys_kill(l, v, retval));
578 }
579
580 int
581 linux_sys_kill(l, v, retval)
582 struct lwp *l;
583 void *v;
584 register_t *retval;
585 {
586 struct linux_sys_kill_args /* {
587 syscallarg(int) pid;
588 syscallarg(int) signum;
589 } */ *uap = v;
590
591 struct sys_kill_args ka;
592 int sig;
593
594 SCARG(&ka, pid) = SCARG(uap, pid);
595 sig = SCARG(uap, signum);
596 if (sig < 0 || sig >= LINUX__NSIG)
597 return (EINVAL);
598 SCARG(&ka, signum) = linux_to_native_sig[sig];
599 return sys_kill(l, &ka, retval);
600 }
601
602 #ifdef LINUX_SS_ONSTACK
603 static void linux_to_native_sigaltstack __P((struct sigaltstack *,
604 const struct linux_sigaltstack *));
605 static void native_to_linux_sigaltstack __P((struct linux_sigaltstack *,
606 const struct sigaltstack *));
607
608 static void
609 linux_to_native_sigaltstack(bss, lss)
610 struct sigaltstack *bss;
611 const struct linux_sigaltstack *lss;
612 {
613 bss->ss_sp = lss->ss_sp;
614 bss->ss_size = lss->ss_size;
615 if (lss->ss_flags & LINUX_SS_ONSTACK)
616 bss->ss_flags = SS_ONSTACK;
617 else if (lss->ss_flags & LINUX_SS_DISABLE)
618 bss->ss_flags = SS_DISABLE;
619 else
620 bss->ss_flags = 0;
621 }
622
623 static void
624 native_to_linux_sigaltstack(lss, bss)
625 struct linux_sigaltstack *lss;
626 const struct sigaltstack *bss;
627 {
628 lss->ss_sp = bss->ss_sp;
629 lss->ss_size = bss->ss_size;
630 if (bss->ss_flags & SS_ONSTACK)
631 lss->ss_flags = LINUX_SS_ONSTACK;
632 else if (bss->ss_flags & SS_DISABLE)
633 lss->ss_flags = LINUX_SS_DISABLE;
634 else
635 lss->ss_flags = 0;
636 }
637
638 int
639 linux_sys_sigaltstack(l, v, retval)
640 struct lwp *l;
641 void *v;
642 register_t *retval;
643 {
644 struct linux_sys_sigaltstack_args /* {
645 syscallarg(const struct linux_sigaltstack *) ss;
646 syscallarg(struct linux_sigaltstack *) oss;
647 } */ *uap = v;
648 struct proc *p = l->l_proc;
649 struct linux_sigaltstack ss;
650 struct sigaltstack nss, oss;
651 int error;
652
653 if (SCARG(uap, ss) != NULL) {
654 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0)
655 return error;
656 linux_to_native_sigaltstack(&nss, &ss);
657 }
658
659 error = sigaltstack1(p,
660 SCARG(uap, ss) ? &nss : NULL, SCARG(uap, oss) ? &oss : NULL);
661 if (error)
662 return error;
663
664 if (SCARG(uap, oss) != NULL) {
665 native_to_linux_sigaltstack(&ss, &oss);
666 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0)
667 return error;
668 }
669 return 0;
670 }
671 #endif
672