linux_signal.c revision 1.18 1 /* $NetBSD: linux_signal.c,v 1.18 1998/10/07 22:45:51 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 linux_old_sigset_t nlss, olss;
329 sigset_t nbss, obss;
330 int error;
331
332 switch (how) {
333 case LINUX_SIG_BLOCK:
334 how = SIG_BLOCK;
335 break;
336 case LINUX_SIG_UNBLOCK:
337 how = SIG_UNBLOCK;
338 break;
339 case LINUX_SIG_SETMASK:
340 how = SIG_SETMASK;
341 break;
342 default:
343 return (EINVAL);
344 }
345
346 if (set) {
347 error = copyin(set, &nlss, sizeof(nlss));
348 if (error)
349 return (error);
350 linux_old_to_native_sigset(&nlss, &nbss);
351 }
352 error = sigprocmask1(p, how,
353 set ? &nbss : 0, oset ? &obss : 0);
354 if (error)
355 return (error);
356 if (oset) {
357 native_to_linux_old_sigset(&obss, &olss);
358 error = copyout(&olss, oset, sizeof(olss));
359 if (error)
360 return (error);
361 }
362 return (error);
363 }
364
365 int
366 linux_sys_rt_sigprocmask(p, v, retval)
367 register struct proc *p;
368 void *v;
369 register_t *retval;
370 {
371 struct linux_sys_rt_sigprocmask_args /* {
372 syscallarg(int) how;
373 syscallarg(const linux_sigset_t *) set;
374 syscallarg(linux_sigset_t *) oset;
375 syscallarg(size_t) sigsetsize;
376 } */ *uap = v;
377
378 /* Use non-rt function: sigsetsize is ignored. */
379 /* Assume sizeof(linux_sigset_t) == sizeof(linux_old_sigset_t) */
380 if (SCARG(uap, sigsetsize) != sizeof(struct linux_old_sigset_t)) {
381 #ifdef LINUX_DEBUG
382 printf("linux_sys_rt_sigprocmask: sigsetsize != sizeof(old_sigset_t)");
383 #endif
384 return(ENOSYS);
385 }
386
387 return(linux_sigprocmask1(p, SCARG(uap, how),
388 (const linux_old_sigset_t *)SCARG(uap, set),
389 (linux_old_sigset_t *)SCARG(uap, oset));
390 }
391
392 int
393 linux_sys_rt_sigpending(p, v, retval)
394 register struct proc *p;
395 void *v;
396 register_t *retval;
397 {
398 struct linux_sys_rt_sigpending_args /* {
399 syscallarg(linux_sigset_t *) set;
400 syscallarg(size_t) sigsetsize;
401 } */ *uap = v;
402 sigset_t bss;
403 linux_sigset_t lss;
404
405 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
406 return (EINVAL);
407
408 sigpending1(p, &bss);
409 native_to_linux_sigset(&bss, &lss);
410 return copyout(&lss, SCARG(uap, set), sizeof(lss));
411 }
412 int
413 linux_sys_sigpending(p, v, retval)
414 register struct proc *p;
415 void *v;
416 register_t *retval;
417 {
418 struct linux_sys_sigpending_args /* {
419 syscallarg(linux_old_sigset_t *) mask;
420 } */ *uap = v;
421 sigset_t bss;
422 linux_old_sigset_t lss;
423
424 sigpending1(p, &bss);
425 native_to_linux_old_sigset(&bss, &lss);
426 return copyout(&lss, SCARG(uap, set), sizeof(lss));
427 }
428
429 int
430 linux_sys_sigsuspend(p, v, retval)
431 register struct proc *p;
432 void *v;
433 register_t *retval;
434 {
435 struct linux_sys_sigsuspend_args /* {
436 syscallarg(caddr_t) restart;
437 syscallarg(int) oldmask;
438 syscallarg(int) mask;
439 } */ *uap = v;
440 linux_old_sigset_t lss;
441 sigset_t bss;
442
443 lss = SCARG(uap, mask);
444 linux_old_to_native_sigset(&lss, &bss);
445 return (sigsuspend1(p, &bss));
446 }
447 int
448 linux_sys_rt_sigsuspend(p, v, retval)
449 register struct proc *p;
450 void *v;
451 register_t *retval;
452 {
453 struct linux_sys_rt_sigsuspend_args /* {
454 syscallarg(linux_sigset_t *) unewset;
455 syscallarg(size_t) sigsetsize;
456 } */ *uap = v;
457 linux_sigset_t lss;
458 sigset_t bss;
459 int error;
460
461 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
462 return (EINVAL);
463
464 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t));
465 if (error)
466 return (error);
467
468 linux_to_native_sigset(&lss, &bss);
469
470 return (sigsuspend1(p, &bss));
471 }
472
473 /*
474 * Once more: only a signal conversion is needed.
475 * Note: also used as sys_rt_queueinfo. The info field is ignored.
476 */
477 int
478 linux_sys_rt_queueinfo(p, v, retval)
479 register struct proc *p;
480 void *v;
481 register_t *retval;
482 {
483 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */
484 #if 0
485 struct linux_sys_rt_queueinfo_args /* {
486 syscallarg(int) pid;
487 syscallarg(int) signum;
488 syscallarg(siginfo_t *) uinfo;
489 } */ *uap = v;
490 #endif
491
492 /* XXX To really implement this we need to */
493 /* XXX keep a list of queued signals somewhere. */
494 return (linux_sys_kill(p, v, retval));
495 }
496
497 int
498 linux_sys_kill(p, v, retval)
499 register struct proc *p;
500 void *v;
501 register_t *retval;
502 {
503 struct linux_sys_kill_args /* {
504 syscallarg(int) pid;
505 syscallarg(int) signum;
506 } */ *uap = v;
507 struct sys_kill_args ka;
508
509 SCARG(&ka, pid) = SCARG(uap, pid);
510 SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)];
511 return sys_kill(p, &ka, retval);
512 }
513