linux_signal.c revision 1.20 1 /* $NetBSD: linux_signal.c,v 1.20 1998/12/15 19:31:39 itohy 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/param.h>
57 #include <sys/systm.h>
58 #include <sys/namei.h>
59 #include <sys/proc.h>
60 #include <sys/filedesc.h>
61 #include <sys/ioctl.h>
62 #include <sys/mount.h>
63 #include <sys/kernel.h>
64 #include <sys/signal.h>
65 #include <sys/signalvar.h>
66 #include <sys/malloc.h>
67
68 #include <sys/syscallargs.h>
69
70 #include <compat/linux/common/linux_types.h>
71 #include <compat/linux/common/linux_signal.h>
72 #include <compat/linux/common/linux_siginfo.h>
73 #include <compat/linux/common/linux_util.h>
74
75 #include <compat/linux/linux_syscallargs.h>
76
77 /* Locally used defines (in bsd<->linux conversion functions): */
78 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s)))
79 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
80 & (1 << ((n) - 1) % LINUX__NSIG_BPW))
81 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
82 |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
83
84 /* Note: linux_to_native_sig[] is in <arch>/linux_sigarray.c */
85 int native_to_linux_sig[NSIG] = {
86 0,
87 LINUX_SIGHUP,
88 LINUX_SIGINT,
89 LINUX_SIGQUIT,
90 LINUX_SIGILL,
91 LINUX_SIGTRAP,
92 LINUX_SIGABRT,
93 0, /* SIGEMT */
94 LINUX_SIGFPE,
95 LINUX_SIGKILL,
96 LINUX_SIGBUS,
97 LINUX_SIGSEGV,
98 0, /* SIGSEGV */
99 LINUX_SIGPIPE,
100 LINUX_SIGALRM,
101 LINUX_SIGTERM,
102 LINUX_SIGURG,
103 LINUX_SIGSTOP,
104 LINUX_SIGTSTP,
105 LINUX_SIGCONT,
106 LINUX_SIGCHLD,
107 LINUX_SIGTTIN,
108 LINUX_SIGTTOU,
109 LINUX_SIGIO,
110 LINUX_SIGXCPU,
111 LINUX_SIGXFSZ,
112 LINUX_SIGVTALRM,
113 LINUX_SIGPROF,
114 LINUX_SIGWINCH,
115 0, /* SIGINFO */
116 LINUX_SIGUSR1,
117 LINUX_SIGUSR2,
118 LINUX_SIGPWR,
119 };
120
121 /*
122 * Convert between Linux and BSD signal sets.
123 */
124 #if LINUX__NSIG_WORDS > 1
125 void
126 linux_old_extra_to_native_sigset(lss, extra, bss)
127 const linux_old_sigset_t *lss;
128 const unsigned long *extra;
129 sigset_t *bss;
130 {
131 linux_sigset_t lsnew;
132
133 /* convert old sigset to new sigset */
134 linux_sigemptyset(&lsnew);
135 lsnew.sig[0] = *lss;
136 if (extra)
137 bcopy(extra, &lsnew.sig[1],
138 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
139
140 linux_to_native_sigset(&lsnew, bss);
141 }
142
143 void
144 native_to_linux_old_extra_sigset(bss, lss, extra)
145 const sigset_t *bss;
146 linux_old_sigset_t *lss;
147 unsigned long *extra;
148 {
149 linux_sigset_t lsnew;
150
151 native_to_linux_sigset(bss, &lsnew);
152
153 /* convert new sigset to old sigset */
154 *lss = lsnew.sig[0];
155 if (extra)
156 bcopy(&lsnew.sig[1], extra,
157 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
158 }
159 #endif
160
161 void
162 linux_to_native_sigset(lss, bss)
163 const linux_sigset_t *lss;
164 sigset_t *bss;
165 {
166 int i, newsig;
167
168 sigemptyset(bss);
169 for (i = 1; i < LINUX__NSIG; i++) {
170 if (linux_sigismember(lss, i)) {
171 newsig = linux_to_native_sig[i];
172 if (newsig)
173 sigaddset(bss, newsig);
174 }
175 }
176 }
177
178 void
179 native_to_linux_sigset(bss, lss)
180 const sigset_t *bss;
181 linux_sigset_t *lss;
182 {
183 int i, newsig;
184
185 linux_sigemptyset(lss);
186 for (i = 1; i < NSIG; i++) {
187 if (sigismember(bss, i)) {
188 newsig = native_to_linux_sig[i];
189 if (newsig)
190 linux_sigaddset(lss, newsig);
191 }
192 }
193 }
194
195 /*
196 * Convert between Linux and BSD sigaction structures. Linux sometimes
197 * has one extra field (sa_restorer) which we don't support.
198 */
199 void
200 linux_old_to_native_sigaction(lsa, bsa)
201 struct linux_old_sigaction *lsa;
202 struct sigaction *bsa;
203 {
204
205 bsa->sa_handler = lsa->sa_handler;
206 linux_old_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask);
207 bsa->sa_flags = 0;
208 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
209 bsa->sa_flags |= SA_NOCLDSTOP;
210 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
211 bsa->sa_flags |= SA_ONSTACK;
212 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
213 bsa->sa_flags |= SA_RESTART;
214 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
215 bsa->sa_flags |= SA_RESETHAND;
216 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
217 bsa->sa_flags |= SA_NODEFER;
218 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
219 bsa->sa_flags |= SA_SIGINFO;
220 #ifdef DEBUG
221 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0)
222 /*XXX*/ printf("linux_old_to_native_sigaction: extra bits ignored\n");
223 if (lsa->sa_restorer != 0)
224 /*XXX*/ printf("linux_old_to_native_sigaction: sa_restorer ignored\n");
225 #endif
226 }
227
228 void
229 native_to_linux_old_sigaction(bsa, lsa)
230 struct sigaction *bsa;
231 struct linux_old_sigaction *lsa;
232 {
233
234 /* Clear sa_flags and sa_restorer (if it exists) */
235 bzero(lsa, sizeof(struct linux_old_sigaction));
236
237 /* ...and fill in the mask and flags */
238 native_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
239 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
240 lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
241 if ((bsa->sa_flags & SA_ONSTACK) != 0)
242 lsa->sa_flags |= LINUX_SA_ONSTACK;
243 if ((bsa->sa_flags & SA_RESTART) != 0)
244 lsa->sa_flags |= LINUX_SA_RESTART;
245 if ((bsa->sa_flags & SA_NODEFER) != 0)
246 lsa->sa_flags |= LINUX_SA_NOMASK;
247 if ((bsa->sa_flags & SA_RESETHAND) != 0)
248 lsa->sa_flags |= LINUX_SA_ONESHOT;
249 if ((bsa->sa_flags & SA_SIGINFO) != 0)
250 lsa->sa_flags |= LINUX_SA_SIGINFO;
251 lsa->sa_handler = bsa->sa_handler;
252 }
253
254 /* ...and the new sigaction conversion funcs. */
255 void
256 linux_to_native_sigaction(lsa, bsa)
257 struct linux_sigaction *lsa;
258 struct sigaction *bsa;
259 {
260
261 bsa->sa_handler = lsa->sa_handler;
262 linux_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask);
263 bsa->sa_flags = 0;
264 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
265 bsa->sa_flags |= SA_NOCLDSTOP;
266 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
267 bsa->sa_flags |= SA_ONSTACK;
268 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
269 bsa->sa_flags |= SA_RESTART;
270 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
271 bsa->sa_flags |= SA_RESETHAND;
272 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
273 bsa->sa_flags |= SA_NODEFER;
274 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
275 bsa->sa_flags |= SA_SIGINFO;
276 #ifdef DEBUG
277 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0)
278 /*XXX*/ printf("linux_to_native_sigaction: extra bits ignored\n");
279 if (lsa->sa_restorer != 0)
280 /*XXX*/ printf("linux_to_native_sigaction: sa_restorer ignored\n");
281 #endif
282 }
283
284 void
285 native_to_linux_sigaction(bsa, lsa)
286 struct sigaction *bsa;
287 struct linux_sigaction *lsa;
288 {
289
290 /* Clear sa_flags and sa_restorer (if it exists) */
291 bzero(lsa, sizeof(struct linux_sigaction));
292
293 /* ...and fill in the mask and flags */
294 native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
295 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
296 lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
297 if ((bsa->sa_flags & SA_ONSTACK) != 0)
298 lsa->sa_flags |= LINUX_SA_ONSTACK;
299 if ((bsa->sa_flags & SA_RESTART) != 0)
300 lsa->sa_flags |= LINUX_SA_RESTART;
301 if ((bsa->sa_flags & SA_NODEFER) != 0)
302 lsa->sa_flags |= LINUX_SA_NOMASK;
303 if ((bsa->sa_flags & SA_RESETHAND) != 0)
304 lsa->sa_flags |= LINUX_SA_ONESHOT;
305 if ((bsa->sa_flags & SA_SIGINFO) != 0)
306 lsa->sa_flags |= LINUX_SA_SIGINFO;
307 lsa->sa_handler = bsa->sa_handler;
308 }
309
310 /* ----------------------------------------------------------------------- */
311
312 /*
313 * The Linux sigaction() system call. Do the usual conversions,
314 * and just call sigaction(). Some flags and values are silently
315 * ignored (see above).
316 */
317 int
318 linux_sys_rt_sigaction(p, v, retval)
319 register struct proc *p;
320 void *v;
321 register_t *retval;
322 {
323 struct linux_sys_rt_sigaction_args /* {
324 syscallarg(int) signum;
325 syscallarg(const struct linux_sigaction *) nsa;
326 syscallarg(struct linux_sigaction *) osa;
327 syscallarg(size_t) sigsetsize;
328 } */ *uap = v;
329 struct linux_sigaction nlsa, olsa;
330 struct sigaction nbsa, obsa;
331 int error;
332
333 /* XXX XAX linux_sigset_t or struct linux_sigaction here? */
334 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
335 return (EINVAL);
336
337 if (SCARG(uap, nsa)) {
338 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
339 if (error)
340 return (error);
341 linux_to_native_sigaction(&nlsa, &nbsa);
342 }
343 error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)],
344 SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0);
345 if (error)
346 return (error);
347 if (SCARG(uap, osa)) {
348 native_to_linux_sigaction(&obsa, &olsa);
349 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
350 if (error)
351 return (error);
352 }
353 return (0);
354 }
355
356 int
357 linux_sigprocmask1(p, how, set, oset)
358 register struct proc *p;
359 int how;
360 const linux_old_sigset_t *set;
361 linux_old_sigset_t *oset;
362 {
363 linux_old_sigset_t nlss, olss;
364 sigset_t nbss, obss;
365 int error;
366
367 switch (how) {
368 case LINUX_SIG_BLOCK:
369 how = SIG_BLOCK;
370 break;
371 case LINUX_SIG_UNBLOCK:
372 how = SIG_UNBLOCK;
373 break;
374 case LINUX_SIG_SETMASK:
375 how = SIG_SETMASK;
376 break;
377 default:
378 return (EINVAL);
379 }
380
381 if (set) {
382 error = copyin(set, &nlss, sizeof(nlss));
383 if (error)
384 return (error);
385 linux_old_to_native_sigset(&nlss, &nbss);
386 }
387 error = sigprocmask1(p, how,
388 set ? &nbss : 0, oset ? &obss : 0);
389 if (error)
390 return (error);
391 if (oset) {
392 native_to_linux_old_sigset(&obss, &olss);
393 error = copyout(&olss, oset, sizeof(olss));
394 if (error)
395 return (error);
396 }
397 return (error);
398 }
399
400 int
401 linux_sys_rt_sigprocmask(p, v, retval)
402 register struct proc *p;
403 void *v;
404 register_t *retval;
405 {
406 struct linux_sys_rt_sigprocmask_args /* {
407 syscallarg(int) how;
408 syscallarg(const linux_sigset_t *) set;
409 syscallarg(linux_sigset_t *) oset;
410 syscallarg(size_t) sigsetsize;
411 } */ *uap = v;
412
413 /* Use non-rt function: sigsetsize is ignored. */
414 /* Assume sizeof(linux_sigset_t) == sizeof(linux_old_sigset_t) */
415 if (SCARG(uap, sigsetsize) != sizeof(linux_old_sigset_t)) {
416 #ifdef LINUX_DEBUG
417 printf("linux_sys_rt_sigprocmask: sigsetsize != sizeof(old_sigset_t)");
418 #endif
419 return(ENOSYS);
420 }
421
422 return(linux_sigprocmask1(p, SCARG(uap, how),
423 (const linux_old_sigset_t *)SCARG(uap, set),
424 (linux_old_sigset_t *)SCARG(uap, oset)));
425 }
426
427 int
428 linux_sys_rt_sigpending(p, v, retval)
429 register struct proc *p;
430 void *v;
431 register_t *retval;
432 {
433 struct linux_sys_rt_sigpending_args /* {
434 syscallarg(linux_sigset_t *) set;
435 syscallarg(size_t) sigsetsize;
436 } */ *uap = v;
437 sigset_t bss;
438 linux_sigset_t lss;
439
440 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
441 return (EINVAL);
442
443 sigpending1(p, &bss);
444 native_to_linux_sigset(&bss, &lss);
445 return copyout(&lss, SCARG(uap, set), sizeof(lss));
446 }
447 int
448 linux_sys_sigpending(p, v, retval)
449 register struct proc *p;
450 void *v;
451 register_t *retval;
452 {
453 struct linux_sys_sigpending_args /* {
454 syscallarg(linux_old_sigset_t *) mask;
455 } */ *uap = v;
456 sigset_t bss;
457 linux_old_sigset_t lss;
458
459 sigpending1(p, &bss);
460 native_to_linux_old_sigset(&bss, &lss);
461 return copyout(&lss, SCARG(uap, set), sizeof(lss));
462 }
463
464 int
465 linux_sys_sigsuspend(p, v, retval)
466 register struct proc *p;
467 void *v;
468 register_t *retval;
469 {
470 struct linux_sys_sigsuspend_args /* {
471 syscallarg(caddr_t) restart;
472 syscallarg(int) oldmask;
473 syscallarg(int) mask;
474 } */ *uap = v;
475 linux_old_sigset_t lss;
476 sigset_t bss;
477
478 lss = SCARG(uap, mask);
479 linux_old_to_native_sigset(&lss, &bss);
480 return (sigsuspend1(p, &bss));
481 }
482 int
483 linux_sys_rt_sigsuspend(p, v, retval)
484 register struct proc *p;
485 void *v;
486 register_t *retval;
487 {
488 struct linux_sys_rt_sigsuspend_args /* {
489 syscallarg(linux_sigset_t *) unewset;
490 syscallarg(size_t) sigsetsize;
491 } */ *uap = v;
492 linux_sigset_t lss;
493 sigset_t bss;
494 int error;
495
496 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
497 return (EINVAL);
498
499 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t));
500 if (error)
501 return (error);
502
503 linux_to_native_sigset(&lss, &bss);
504
505 return (sigsuspend1(p, &bss));
506 }
507
508 /*
509 * Once more: only a signal conversion is needed.
510 * Note: also used as sys_rt_queueinfo. The info field is ignored.
511 */
512 int
513 linux_sys_rt_queueinfo(p, v, retval)
514 register struct proc *p;
515 void *v;
516 register_t *retval;
517 {
518 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */
519 #if 0
520 struct linux_sys_rt_queueinfo_args /* {
521 syscallarg(int) pid;
522 syscallarg(int) signum;
523 syscallarg(siginfo_t *) uinfo;
524 } */ *uap = v;
525 #endif
526
527 /* XXX To really implement this we need to */
528 /* XXX keep a list of queued signals somewhere. */
529 return (linux_sys_kill(p, v, retval));
530 }
531
532 int
533 linux_sys_kill(p, v, retval)
534 register struct proc *p;
535 void *v;
536 register_t *retval;
537 {
538 struct linux_sys_kill_args /* {
539 syscallarg(int) pid;
540 syscallarg(int) signum;
541 } */ *uap = v;
542 struct sys_kill_args ka;
543
544 SCARG(&ka, pid) = SCARG(uap, pid);
545 SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)];
546 return sys_kill(p, &ka, retval);
547 }
548