linux_signal.c revision 1.4 1 /* $NetBSD: linux_signal.c,v 1.4 1995/06/22 21:34:39 fvdl Exp $ */
2
3 /*
4 * Copyright (c) 1995 Frank van der Linden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Frank van der Linden
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
34 */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/namei.h>
39 #include <sys/proc.h>
40 #include <sys/filedesc.h>
41 #include <sys/ioctl.h>
42 #include <sys/mount.h>
43 #include <sys/kernel.h>
44 #include <sys/signal.h>
45 #include <sys/signalvar.h>
46 #include <sys/malloc.h>
47 #include <sys/exec.h>
48
49 #include <sys/syscallargs.h>
50
51 #include <compat/linux/linux_types.h>
52 #include <compat/linux/linux_syscallargs.h>
53 #include <compat/linux/linux_util.h>
54 #include <compat/linux/linux_signal.h>
55
56 /*
57 * Most of ths stuff in this file is taken from Christos' SVR4 emul
58 * code. The things that need to be done are largely the same, so
59 * re-inventing the wheel doesn't make much sense.
60 */
61
62 /*
63 * Some boring signal conversion functions. Just a switch() for all signals;
64 * return the converted signal number, 0 if not supported.
65 */
66
67 int
68 bsd_to_linux_sig(sig)
69 int sig;
70 {
71 switch(sig) {
72 case SIGHUP:
73 return LINUX_SIGHUP;
74 case SIGINT:
75 return LINUX_SIGINT;
76 case SIGQUIT:
77 return LINUX_SIGQUIT;
78 case SIGILL:
79 return LINUX_SIGILL;
80 case SIGTRAP:
81 return LINUX_SIGTRAP;
82 case SIGABRT:
83 return LINUX_SIGABRT;
84 case SIGFPE:
85 return LINUX_SIGFPE;
86 case SIGKILL:
87 return LINUX_SIGKILL;
88 case SIGBUS:
89 return LINUX_SIGBUS;
90 case SIGSEGV:
91 return LINUX_SIGSEGV;
92 case SIGPIPE:
93 return LINUX_SIGPIPE;
94 case SIGALRM:
95 return LINUX_SIGALRM;
96 case SIGTERM:
97 return LINUX_SIGTERM;
98 case SIGURG:
99 return LINUX_SIGURG;
100 case SIGSTOP:
101 return LINUX_SIGSTOP;
102 case SIGTSTP:
103 return LINUX_SIGTSTP;
104 case SIGCONT:
105 return LINUX_SIGCONT;
106 case SIGCHLD:
107 return LINUX_SIGCHLD;
108 case SIGTTIN:
109 return LINUX_SIGTTIN;
110 case SIGTTOU:
111 return LINUX_SIGTTOU;
112 case SIGIO:
113 return LINUX_SIGIO;
114 case SIGXCPU:
115 return LINUX_SIGXCPU;
116 case SIGXFSZ:
117 return LINUX_SIGXFSZ;
118 case SIGVTALRM:
119 return LINUX_SIGVTALRM;
120 case SIGPROF:
121 return LINUX_SIGPROF;
122 case SIGWINCH:
123 return LINUX_SIGWINCH;
124 case SIGUSR1:
125 return LINUX_SIGUSR1;
126 case SIGUSR2:
127 return LINUX_SIGUSR2;
128 /* Not supported: EMT, SYS, INFO */
129 }
130 return 0;
131 }
132
133 int
134 linux_to_bsd_sig(sig)
135 int sig;
136 {
137 switch(sig) {
138 case LINUX_SIGHUP:
139 return SIGHUP;
140 case LINUX_SIGINT:
141 return SIGINT;
142 case LINUX_SIGQUIT:
143 return SIGQUIT;
144 case LINUX_SIGILL:
145 return SIGILL;
146 case LINUX_SIGTRAP:
147 return SIGTRAP;
148 case LINUX_SIGABRT:
149 return SIGABRT;
150 case LINUX_SIGBUS:
151 return SIGBUS;
152 case LINUX_SIGFPE:
153 return SIGFPE;
154 case LINUX_SIGKILL:
155 return SIGKILL;
156 case LINUX_SIGUSR1:
157 return SIGUSR1;
158 case LINUX_SIGSEGV:
159 return SIGSEGV;
160 case LINUX_SIGUSR2:
161 return SIGUSR2;
162 case LINUX_SIGPIPE:
163 return SIGPIPE;
164 case LINUX_SIGALRM:
165 return SIGALRM;
166 case LINUX_SIGTERM:
167 return SIGTERM;
168 case LINUX_SIGCHLD:
169 return SIGCHLD;
170 case LINUX_SIGCONT:
171 return SIGCONT;
172 case LINUX_SIGSTOP:
173 return SIGSTOP;
174 case LINUX_SIGTSTP:
175 return SIGTSTP;
176 case LINUX_SIGTTIN:
177 return SIGTTIN;
178 case LINUX_SIGTTOU:
179 return SIGTTOU;
180 case LINUX_SIGURG:
181 return SIGURG;
182 case LINUX_SIGXCPU:
183 return SIGXCPU;
184 case LINUX_SIGXFSZ:
185 return SIGXFSZ;
186 case LINUX_SIGVTALRM:
187 return SIGVTALRM;
188 case LINUX_SIGPROF:
189 return SIGPROF;
190 case LINUX_SIGWINCH:
191 return SIGWINCH;
192 case LINUX_SIGIO:
193 return SIGIO;
194 /* Not supported: STKFLT, PWR */
195 }
196 return 0;
197 }
198
199 /*
200 * Ok, we know that Linux and BSD signals both are just an unsigned int.
201 * Don't bother to use the sigismember() stuff for now.
202 */
203 static void
204 linux_to_bsd_sigset(lss, bss)
205 const linux_sigset_t *lss;
206 sigset_t *bss;
207 {
208 int i, newsig;
209
210 *bss = (sigset_t) 0;
211 for (i = 1; i <= LINUX_NSIG; i++) {
212 if (*lss & sigmask(i)) {
213 newsig = linux_to_bsd_sig(i);
214 if (newsig)
215 *bss |= sigmask(newsig);
216 }
217 }
218 }
219
220 void
221 bsd_to_linux_sigset(bss, lss)
222 const sigset_t *bss;
223 linux_sigset_t *lss;
224 {
225 int i, newsig;
226
227 *lss = (linux_sigset_t) 0;
228 for (i = 1; i <= NSIG; i++) {
229 if (*bss & sigmask(i)) {
230 newsig = bsd_to_linux_sig(i);
231 if (newsig)
232 *lss |= sigmask(newsig);
233 }
234 }
235 }
236
237 /*
238 * Convert between Linux and BSD sigaction structures. Linux has
239 * one extra field (sa_restorer) which we don't support. The Linux
240 * SA_ONESHOT and SA_NOMASK flags (which together form the old
241 * SysV signal behavior) are silently ignored. XXX
242 */
243 void
244 linux_to_bsd_sigaction(lsa, bsa)
245 struct linux_sigaction *lsa;
246 struct sigaction *bsa;
247 {
248 bsa->sa_handler = lsa->sa_handler;
249 linux_to_bsd_sigset(&bsa->sa_mask, &lsa->sa_mask);
250 bsa->sa_flags = 0;
251 bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_NOCLDSTOP,
252 SA_NOCLDSTOP);
253 bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_ONSTACK,
254 SA_ONSTACK);
255 bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_RESTART,
256 SA_RESTART);
257 }
258
259 void
260 bsd_to_linux_sigaction(bsa, lsa)
261 struct sigaction *bsa;
262 struct linux_sigaction *lsa;
263 {
264 lsa->sa_handler = bsa->sa_handler;
265 bsd_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask);
266 lsa->sa_flags = 0;
267 lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_NOCLDSTOP,
268 LINUX_SA_NOCLDSTOP);
269 lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_ONSTACK,
270 LINUX_SA_ONSTACK);
271 lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_RESTART,
272 LINUX_SA_RESTART);
273 lsa->sa_restorer = NULL;
274 }
275
276
277 /*
278 * The Linux sigaction() system call. Do the usual conversions,
279 * and just call sigaction(). Some flags and values are silently
280 * ignored (see above).
281 */
282 int
283 linux_sigaction(p, uap, retval)
284 register struct proc *p;
285 struct linux_sigaction_args /* {
286 syscallarg(int) signum;
287 syscallarg(struct linux_sigaction *) nsa;
288 syscallarg(struct linux_sigaction *) osa;
289 } */ *uap;
290 register_t *retval;
291 {
292 struct sigaction *nbsda = NULL, *obsda = NULL, tmpbsda;
293 struct linux_sigaction *nlsa, *olsa, tmplsa;
294 struct sigaction_args sa;
295 caddr_t sg;
296 int error;
297
298 sg = stackgap_init();
299 olsa = SCARG(uap, osa);
300 nlsa = SCARG(uap, nsa);
301
302 if (olsa != NULL)
303 obsda = stackgap_alloc(&sg, sizeof (struct sigaction));
304
305 if (nlsa != NULL) {
306 nbsda = stackgap_alloc(&sg, sizeof (struct sigaction));
307 if ((error = copyin(nlsa, &tmplsa, sizeof tmplsa)))
308 return error;
309 linux_to_bsd_sigaction(&tmplsa, &tmpbsda);
310 if ((error = copyout(&tmpbsda, nbsda, sizeof tmpbsda)))
311 return error;
312 }
313
314 SCARG(&sa, signum) = linux_to_bsd_sig(SCARG(uap, signum));
315 SCARG(&sa, nsa) = nbsda;
316 SCARG(&sa, osa) = obsda;
317
318 if ((error = sigaction(p, &sa, retval)))
319 return error;
320
321 if (olsa != NULL) {
322 if ((error = copyin(obsda, &tmpbsda, sizeof tmpbsda)))
323 return error;
324 bsd_to_linux_sigaction(&tmpbsda, &tmplsa);
325 if ((error = copyout(&tmplsa, olsa, sizeof tmplsa)))
326 return error;
327 }
328 return 0;
329 }
330
331 /*
332 * The Linux signal() system call. I think that the signal() in the C
333 * library actually calls sigaction, so I doubt this one is ever used.
334 * But hey, it can't hurt having it here. The same restrictions as for
335 * sigaction() apply.
336 */
337 int
338 linux_signal(p, uap, retval)
339 register struct proc *p;
340 struct linux_signal_args /* {
341 syscallarg(int) sig;
342 syscallarg(linux_handler_t) handler;
343 } */ *uap;
344 register_t *retval;
345 {
346 caddr_t sg;
347 struct sigaction_args sa_args;
348 struct sigaction *osa, *nsa, tmpsa;
349 int error;
350
351 sg = stackgap_init();
352 nsa = stackgap_alloc(&sg, sizeof *nsa);
353 osa = stackgap_alloc(&sg, sizeof *osa);
354
355 tmpsa.sa_handler = SCARG(uap, handler);
356 tmpsa.sa_mask = (sigset_t) 0;
357 tmpsa.sa_flags = 0;
358 if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
359 return error;
360
361 SCARG(&sa_args, signum) = linux_to_bsd_sig(SCARG(uap, sig));
362 SCARG(&sa_args, osa) = osa;
363 SCARG(&sa_args, nsa) = nsa;
364 if ((error = sigaction(p, &sa_args, retval)))
365 return error;
366
367 if ((error = copyin(osa, &tmpsa, sizeof *osa)))
368 return error;
369 retval[0] = (register_t) tmpsa.sa_handler;
370
371 return 0;
372 }
373
374 /*
375 * This is just a copy of the svr4 compat one. I feel so creative now.
376 */
377 int
378 linux_sigprocmask(p, uap, retval)
379 register struct proc *p;
380 register struct linux_sigprocmask_args /* {
381 syscallarg(int) how;
382 syscallarg(linux_sigset_t *) set;
383 syscallarg(linux_sigset_t * oset;
384 } */ *uap;
385 register_t *retval;
386 {
387 linux_sigset_t ss;
388 sigset_t bs;
389 int error = 0;
390
391 *retval = 0;
392
393 if (SCARG(uap, oset) != NULL) {
394 /* Fix the return value first if needed */
395 bsd_to_linux_sigset(&p->p_sigmask, &ss);
396 if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
397 return error;
398 }
399
400 if (SCARG(uap, set) == NULL)
401 /* Just examine */
402 return 0;
403
404 if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
405 return error;
406
407 linux_to_bsd_sigset(&ss, &bs);
408
409 (void) splhigh();
410
411 switch (SCARG(uap, how)) {
412 case LINUX_SIG_BLOCK:
413 p->p_sigmask |= bs & ~sigcantmask;
414 break;
415
416 case LINUX_SIG_UNBLOCK:
417 p->p_sigmask &= ~bs;
418 break;
419
420 case LINUX_SIG_SETMASK:
421 p->p_sigmask = bs & ~sigcantmask;
422 break;
423
424 default:
425 error = EINVAL;
426 break;
427 }
428
429 (void) spl0();
430
431 return error;
432 }
433
434 /*
435 * The functions below really make no distinction between an int
436 * and [linux_]sigset_t. This is ok for now, but it might break
437 * sometime. Then again, sigset_t is trusted to be an int everywhere
438 * else in the kernel too.
439 */
440 /* ARGSUSED */
441 int
442 linux_siggetmask(p, uap, retval)
443 struct proc *p;
444 void *uap;
445 register_t *retval;
446 {
447 bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *) retval);
448 return 0;
449 }
450
451 /*
452 * The following three functions fiddle with a process' signal mask.
453 * Convert the signal masks because of the different signal
454 * values for Linux. The need for this is the reason why
455 * they are here, and have not been mapped directly.
456 */
457 int
458 linux_sigsetmask(p, uap, retval)
459 struct proc *p;
460 struct linux_sigsetmask_args /* {
461 syscallarg(linux_sigset_t) mask;
462 } */ *uap;
463 register_t *retval;
464 {
465 linux_sigset_t mask;
466 sigset_t bsdsig;
467
468 bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *) retval);
469
470 mask = SCARG(uap, mask);
471 bsd_to_linux_sigset(&mask, &bsdsig);
472
473 splhigh();
474 p->p_sigmask = bsdsig & ~sigcantmask;
475 spl0();
476
477 return 0;
478 }
479
480 int
481 linux_sigpending(p, uap, retval)
482 struct proc *p;
483 struct linux_sigpending_args /* {
484 syscallarg(linux_sigset_t *) mask;
485 } */ *uap;
486 register_t *retval;
487 {
488 sigset_t bsdsig;
489 linux_sigset_t linuxsig;
490
491 bsdsig = p->p_siglist & p->p_sigmask;
492
493 bsd_to_linux_sigset(&bsdsig, &linuxsig);
494 return copyout(&linuxsig, SCARG(uap, mask), sizeof linuxsig);
495 }
496
497 int
498 linux_sigsuspend(p, uap, retval)
499 struct proc *p;
500 struct linux_sigsuspend_args /* {
501 syscallarg(caddr_t) restart;
502 syscallarg(int) oldmask;
503 syscallarg(int) mask;
504 } */ *uap;
505 register_t *retval;
506 {
507 struct sigsuspend_args ssa;
508
509 linux_to_bsd_sigset(&SCARG(uap, mask), &SCARG(&ssa, mask));
510 return sigsuspend(p, &ssa, retval);
511 }
512
513 /*
514 * The deprecated pause(2), which is really just an instance
515 * of sigsuspend(2).
516 */
517 int
518 linux_pause(p, uap, retval)
519 struct proc *p;
520 void *uap;
521 register_t *retval;
522 {
523 struct sigsuspend_args bsa;
524
525 SCARG(&bsa, mask) = p->p_sigmask;
526 return sigsuspend(p, &bsa, retval);
527 }
528
529 /*
530 * Once more: only a signal conversion is needed.
531 */
532 int
533 linux_kill(p, uap, retval)
534 struct proc *p;
535 struct linux_kill_args /* {
536 syscallarg(int) pid;
537 syscallarg(int) signum;
538 } */ *uap;
539 register_t *retval;
540 {
541 SCARG(uap, signum) = linux_to_bsd_sig(SCARG(uap, signum));
542 return kill(p, (struct kill_args *) uap, retval);
543 }
544