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