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