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