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