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