Annotation of sys/compat/linux/linux_signal.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: linux_signal.c,v 1.12 2003/02/25 09:10:27 tedu Exp $ */
2: /* $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Frank van der Linden
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project
19: * by Frank van der Linden
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: *
34: * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
35: */
36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
39: #include <sys/namei.h>
40: #include <sys/proc.h>
41: #include <sys/filedesc.h>
42: #include <sys/ioctl.h>
43: #include <sys/mount.h>
44: #include <sys/kernel.h>
45: #include <sys/signal.h>
46: #include <sys/signalvar.h>
47: #include <sys/malloc.h>
48:
49: #include <sys/syscallargs.h>
50:
51: #include <compat/linux/linux_types.h>
52: #include <compat/linux/linux_signal.h>
53: #include <compat/linux/linux_syscallargs.h>
54: #include <compat/linux/linux_util.h>
55:
56: #define sigemptyset(s) bzero((s), sizeof(*(s)))
57: #define sigismember(s, n) (*(s) & sigmask(n))
58: #define sigaddset(s, n) (*(s) |= sigmask(n))
59:
60: /* Locally used defines (in bsd<->linux conversion functions): */
61: #define linux_sigmask(n) (1 << ((n) - 1))
62: #define linux_sigemptyset(s) bzero((s), sizeof(*(s)))
63: #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
64: & (1 << ((n) - 1) % LINUX__NSIG_BPW))
65: #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
66: |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
67:
68: int bsd_to_linux_sig[NSIG] = {
69: 0,
70: LINUX_SIGHUP,
71: LINUX_SIGINT,
72: LINUX_SIGQUIT,
73: LINUX_SIGILL,
74: LINUX_SIGTRAP,
75: LINUX_SIGABRT,
76: LINUX_NSIG, /* XXX Kludge to get RT signal #32 to work */
77: LINUX_SIGFPE,
78: LINUX_SIGKILL,
79: LINUX_SIGBUS,
80: LINUX_SIGSEGV,
81: LINUX_NSIG + 1, /* XXX Kludge to get RT signal #32 to work */
82: LINUX_SIGPIPE,
83: LINUX_SIGALRM,
84: LINUX_SIGTERM,
85: LINUX_SIGURG,
86: LINUX_SIGSTOP,
87: LINUX_SIGTSTP,
88: LINUX_SIGCONT,
89: LINUX_SIGCHLD,
90: LINUX_SIGTTIN,
91: LINUX_SIGTTOU,
92: LINUX_SIGIO,
93: LINUX_SIGXCPU,
94: LINUX_SIGXFSZ,
95: LINUX_SIGVTALRM,
96: LINUX_SIGPROF,
97: LINUX_SIGWINCH,
98: 0, /* SIGINFO */
99: LINUX_SIGUSR1,
100: LINUX_SIGUSR2,
101: };
102:
103: int linux_to_bsd_sig[LINUX__NSIG] = {
104: 0,
105: SIGHUP,
106: SIGINT,
107: SIGQUIT,
108: SIGILL,
109: SIGTRAP,
110: SIGABRT,
111: SIGBUS,
112: SIGFPE,
113: SIGKILL,
114: SIGUSR1,
115: SIGSEGV,
116: SIGUSR2,
117: SIGPIPE,
118: SIGALRM,
119: SIGTERM,
120: 0, /* SIGSTKFLT */
121: SIGCHLD,
122: SIGCONT,
123: SIGSTOP,
124: SIGTSTP,
125: SIGTTIN,
126: SIGTTOU,
127: SIGURG,
128: SIGXCPU,
129: SIGXFSZ,
130: SIGVTALRM,
131: SIGPROF,
132: SIGWINCH,
133: SIGIO,
134: 0, /* SIGUNUSED */
135: 0,
136: SIGEMT, /* XXX Gruesome hack for linuxthreads: */
137: SIGSYS, /* Map 1st 2 RT signals onto ones we handle. */
138: 0,
139: 0,
140: 0,
141: 0,
142: 0,
143: 0,
144: 0,
145: 0,
146: 0,
147: 0,
148: 0,
149: 0,
150: 0,
151: 0,
152: 0,
153: 0,
154: 0,
155: 0,
156: 0,
157: 0,
158: 0,
159: 0,
160: 0,
161: 0,
162: 0,
163: 0,
164: 0,
165: 0,
166: 0,
167: 0,
168: };
169:
170: /*
171: * Convert between Linux and BSD signal sets.
172: */
173: void
174: linux_old_to_bsd_sigset(lss, bss)
175: const linux_old_sigset_t *lss;
176: sigset_t *bss;
177: {
178: linux_old_extra_to_bsd_sigset(lss, (const unsigned long *) 0, bss);
179: }
180:
181: void
182: bsd_to_linux_old_sigset(bss, lss)
183: const sigset_t *bss;
184: linux_old_sigset_t *lss;
185: {
186: bsd_to_linux_old_extra_sigset(bss, lss, (unsigned long *) 0);
187: }
188:
189: void
190: linux_old_extra_to_bsd_sigset(lss, extra, bss)
191: const linux_old_sigset_t *lss;
192: const unsigned long *extra;
193: sigset_t *bss;
194: {
195: linux_sigset_t lsnew;
196:
197: /* convert old sigset to new sigset */
198: linux_sigemptyset(&lsnew);
199: lsnew.sig[0] = *lss;
200: if (extra)
201: bcopy(extra, &lsnew.sig[1],
202: sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
203:
204: linux_to_bsd_sigset(&lsnew, bss);
205: }
206:
207: void
208: bsd_to_linux_old_extra_sigset(bss, lss, extra)
209: const sigset_t *bss;
210: linux_old_sigset_t *lss;
211: unsigned long *extra;
212: {
213: linux_sigset_t lsnew;
214:
215: bsd_to_linux_sigset(bss, &lsnew);
216:
217: /* convert new sigset to old sigset */
218: *lss = lsnew.sig[0];
219: if (extra)
220: bcopy(&lsnew.sig[1], extra,
221: sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
222: }
223:
224: void
225: linux_to_bsd_sigset(lss, bss)
226: const linux_sigset_t *lss;
227: sigset_t *bss;
228: {
229: int i, newsig;
230:
231: sigemptyset(bss);
232: for (i = 1; i < LINUX__NSIG; i++) {
233: if (linux_sigismember(lss, i)) {
234: newsig = linux_to_bsd_sig[i];
235: if (newsig)
236: sigaddset(bss, newsig);
237: }
238: }
239: }
240:
241: void
242: bsd_to_linux_sigset(bss, lss)
243: const sigset_t *bss;
244: linux_sigset_t *lss;
245: {
246: int i, newsig;
247:
248: linux_sigemptyset(lss);
249: for (i = 1; i < NSIG; i++) {
250: if (sigismember(bss, i)) {
251: newsig = bsd_to_linux_sig[i];
252: if (newsig)
253: linux_sigaddset(lss, newsig);
254: }
255: }
256: }
257:
258: /*
259: * Convert between Linux and BSD sigaction structures. Linux has
260: * one extra field (sa_restorer) which we don't support.
261: */
262: void
263: linux_old_to_bsd_sigaction(lsa, bsa)
264: struct linux_old_sigaction *lsa;
265: struct sigaction *bsa;
266: {
267:
268: bsa->sa_handler = lsa->sa__handler;
269: linux_old_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
270: bsa->sa_flags = 0;
271: if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
272: bsa->sa_flags |= SA_ONSTACK;
273: if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
274: bsa->sa_flags |= SA_RESTART;
275: if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
276: bsa->sa_flags |= SA_RESETHAND;
277: if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
278: bsa->sa_flags |= SA_NOCLDSTOP;
279: if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
280: bsa->sa_flags |= SA_NODEFER;
281: }
282:
283: void
284: bsd_to_linux_old_sigaction(bsa, lsa)
285: struct sigaction *bsa;
286: struct linux_old_sigaction *lsa;
287: {
288:
289: lsa->sa__handler = bsa->sa_handler;
290: bsd_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
291: lsa->sa_flags = 0;
292: if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
293: lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
294: if ((bsa->sa_flags & SA_ONSTACK) != 0)
295: lsa->sa_flags |= LINUX_SA_ONSTACK;
296: if ((bsa->sa_flags & SA_RESTART) != 0)
297: lsa->sa_flags |= LINUX_SA_RESTART;
298: if ((bsa->sa_flags & SA_NODEFER) != 0)
299: lsa->sa_flags |= LINUX_SA_NOMASK;
300: if ((bsa->sa_flags & SA_RESETHAND) != 0)
301: lsa->sa_flags |= LINUX_SA_ONESHOT;
302: lsa->sa_restorer = NULL;
303: }
304:
305: void
306: linux_to_bsd_sigaction(lsa, bsa)
307: struct linux_sigaction *lsa;
308: struct sigaction *bsa;
309: {
310:
311: bsa->sa_handler = lsa->sa__handler;
312: linux_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
313: bsa->sa_flags = 0;
314: if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
315: bsa->sa_flags |= SA_NOCLDSTOP;
316: if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
317: bsa->sa_flags |= SA_ONSTACK;
318: if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
319: bsa->sa_flags |= SA_RESTART;
320: if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
321: bsa->sa_flags |= SA_RESETHAND;
322: if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
323: bsa->sa_flags |= SA_NODEFER;
324: if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
325: bsa->sa_flags |= SA_SIGINFO;
326: }
327:
328: void
329: bsd_to_linux_sigaction(bsa, lsa)
330: struct sigaction *bsa;
331: struct linux_sigaction *lsa;
332: {
333:
334: /* Clear sa_flags and sa_restorer (if it exists) */
335: bzero(lsa, sizeof(struct linux_sigaction));
336:
337: /* ...and fill in the mask and flags */
338: bsd_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
339: if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
340: lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
341: if ((bsa->sa_flags & SA_ONSTACK) != 0)
342: lsa->sa_flags |= LINUX_SA_ONSTACK;
343: if ((bsa->sa_flags & SA_RESTART) != 0)
344: lsa->sa_flags |= LINUX_SA_RESTART;
345: if ((bsa->sa_flags & SA_NODEFER) != 0)
346: lsa->sa_flags |= LINUX_SA_NOMASK;
347: if ((bsa->sa_flags & SA_RESETHAND) != 0)
348: lsa->sa_flags |= LINUX_SA_ONESHOT;
349: if ((bsa->sa_flags & SA_SIGINFO) != 0)
350: lsa->sa_flags |= LINUX_SA_SIGINFO;
351: lsa->sa__handler = bsa->sa_handler;
352: }
353:
354: int
355: linux_to_bsd_signal(int linuxsig, int *bsdsig)
356: {
357: if (linuxsig < 0 || linuxsig >= LINUX__NSIG)
358: return (EINVAL);
359:
360: *bsdsig = linux_to_bsd_sig[linuxsig];
361: return (0);
362: }
363:
364: int
365: bsd_to_linux_signal(int bsdsig, int *linuxsig)
366: {
367: if (bsdsig < 0 || bsdsig >= NSIG)
368: return (EINVAL);
369:
370: *linuxsig = bsd_to_linux_sig[bsdsig];
371: return (0);
372: }
373:
374: /*
375: * The Linux sigaction() system call. Do the usual conversions,
376: * and just call sigaction(). Some flags and values are silently
377: * ignored (see above).
378: */
379: int
380: linux_sys_sigaction(p, v, retval)
381: register struct proc *p;
382: void *v;
383: register_t *retval;
384: {
385: struct linux_sys_sigaction_args /* {
386: syscallarg(int) signum;
387: syscallarg(struct linux_old_sigaction *) nsa;
388: syscallarg(struct linux_old_sigaction *) osa;
389: } */ *uap = v;
390: struct linux_old_sigaction *nlsa, *olsa, tmplsa;
391: struct sigaction *nbsa, *obsa, tmpbsa;
392: struct sys_sigaction_args sa;
393: caddr_t sg;
394: int error;
395:
396: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
397: return (EINVAL);
398:
399: sg = stackgap_init(p->p_emul);
400: nlsa = SCARG(uap, nsa);
401: olsa = SCARG(uap, osa);
402:
403: if (olsa != NULL)
404: obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
405: else
406: obsa = NULL;
407:
408: if (nlsa != NULL) {
409: nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
410: if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
411: return (error);
412: linux_old_to_bsd_sigaction(&tmplsa, &tmpbsa);
413: if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
414: return (error);
415: } else
416: nbsa = NULL;
417:
418: SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
419: SCARG(&sa, nsa) = nbsa;
420: SCARG(&sa, osa) = obsa;
421:
422: /* Silently ignore unknown signals */
423: if (SCARG(&sa, signum) == 0) {
424: if (obsa != NULL) {
425: obsa->sa_handler = SIG_IGN;
426: sigemptyset(&obsa->sa_mask);
427: obsa->sa_flags = 0;
428: }
429: }
430: else {
431: if ((error = sys_sigaction(p, &sa, retval)) != 0)
432: return (error);
433: }
434:
435: if (olsa != NULL) {
436: if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
437: return (error);
438: bsd_to_linux_old_sigaction(&tmpbsa, &tmplsa);
439: if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
440: return (error);
441: }
442:
443: return (0);
444: }
445:
446: int
447: linux_sys_rt_sigaction(p, v, retval)
448: register struct proc *p;
449: void *v;
450: register_t *retval;
451: {
452: struct linux_sys_rt_sigaction_args /* {
453: syscallarg(int) signum;
454: syscallarg(struct linux_sigaction *) nsa;
455: syscallarg(struct linux_sigaction *) osa;
456: syscallarg(size_t) sigsetsize;
457: } */ *uap = v;
458: struct linux_sigaction *nlsa, *olsa, tmplsa;
459: struct sigaction *nbsa, *obsa, tmpbsa;
460: struct sys_sigaction_args sa;
461: caddr_t sg;
462: int error;
463:
464: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
465: return (EINVAL);
466:
467: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
468: return (EINVAL);
469:
470: sg = stackgap_init(p->p_emul);
471: nlsa = SCARG(uap, nsa);
472: olsa = SCARG(uap, osa);
473:
474: if (olsa != NULL)
475: obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
476: else
477: obsa = NULL;
478:
479: if (nlsa != NULL) {
480: nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
481: if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
482: return (error);
483: linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
484: if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
485: return (error);
486: }
487: else
488: nbsa = NULL;
489:
490: SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
491: SCARG(&sa, nsa) = nbsa;
492: SCARG(&sa, osa) = obsa;
493:
494: /* Silently ignore unknown signals */
495: if (SCARG(&sa, signum) == 0) {
496: if (obsa != NULL) {
497: obsa->sa_handler = SIG_IGN;
498: sigemptyset(&obsa->sa_mask);
499: obsa->sa_flags = 0;
500: }
501: }
502: else {
503: if ((error = sys_sigaction(p, &sa, retval)) != 0)
504: return (error);
505: }
506:
507: if (olsa != NULL) {
508: if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
509: return (error);
510: bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
511: if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
512: return (error);
513: }
514:
515: return (0);
516: }
517:
518: /*
519: * The Linux signal() system call. I think that the signal() in the C
520: * library actually calls sigaction, so I doubt this one is ever used.
521: * But hey, it can't hurt having it here. The same restrictions as for
522: * sigaction() apply.
523: */
524: int
525: linux_sys_signal(p, v, retval)
526: register struct proc *p;
527: void *v;
528: register_t *retval;
529: {
530: struct linux_sys_signal_args /* {
531: syscallarg(int) sig;
532: syscallarg(linux_handler_t) handler;
533: } */ *uap = v;
534: caddr_t sg;
535: struct sys_sigaction_args sa_args;
536: struct sigaction *osa, *nsa, tmpsa;
537: int error;
538:
539: if (SCARG(uap, sig) < 0 || SCARG(uap, sig) >= LINUX__NSIG)
540: return (EINVAL);
541:
542: sg = stackgap_init(p->p_emul);
543: nsa = stackgap_alloc(&sg, sizeof *nsa);
544: osa = stackgap_alloc(&sg, sizeof *osa);
545:
546: tmpsa.sa_handler = SCARG(uap, handler);
547: tmpsa.sa_mask = (sigset_t) 0;
548: tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
549: if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
550: return (error);
551:
552: SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
553: SCARG(&sa_args, osa) = osa;
554: SCARG(&sa_args, nsa) = nsa;
555:
556: /* Silently ignore unknown signals */
557: if (SCARG(&sa_args, signum) != 0) {
558: if ((error = sys_sigaction(p, &sa_args, retval)))
559: return (error);
560: }
561:
562: if ((error = copyin(osa, &tmpsa, sizeof *osa)))
563: return (error);
564: retval[0] = (register_t) tmpsa.sa_handler;
565:
566: return (0);
567: }
568:
569: /*
570: * This is just a copy of the svr4 compat one. I feel so creative now.
571: */
572: int
573: linux_sys_sigprocmask(p, v, retval)
574: register struct proc *p;
575: void *v;
576: register_t *retval;
577: {
578: struct linux_sys_sigprocmask_args /* {
579: syscallarg(int) how;
580: syscallarg(linux_old_sigset_t *) set;
581: syscallarg(linux_old_sigset_t *) oset;
582: } */ *uap = v;
583: linux_old_sigset_t ss;
584: sigset_t bs;
585: int error = 0;
586:
587: *retval = 0;
588:
589: if (SCARG(uap, oset) != NULL) {
590: /* Fix the return value first if needed */
591: bsd_to_linux_old_sigset(&p->p_sigmask, &ss);
592: if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
593: return (error);
594: }
595:
596: if (SCARG(uap, set) == NULL)
597: /* Just examine */
598: return (0);
599:
600: if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
601: return (error);
602:
603: linux_old_to_bsd_sigset(&ss, &bs);
604:
605: (void) splhigh();
606:
607: switch (SCARG(uap, how)) {
608: case LINUX_SIG_BLOCK:
609: p->p_sigmask |= bs & ~sigcantmask;
610: break;
611:
612: case LINUX_SIG_UNBLOCK:
613: p->p_sigmask &= ~bs;
614: break;
615:
616: case LINUX_SIG_SETMASK:
617: p->p_sigmask = bs & ~sigcantmask;
618: break;
619:
620: default:
621: error = EINVAL;
622: break;
623: }
624:
625: (void) spl0();
626:
627: return (error);
628: }
629:
630: int
631: linux_sys_rt_sigprocmask(p, v, retval)
632: register struct proc *p;
633: void *v;
634: register_t *retval;
635: {
636: struct linux_sys_rt_sigprocmask_args /* {
637: syscallarg(int) how;
638: syscallarg(const linux_sigset_t *) set;
639: syscallarg(linux_sigset_t *) oset;
640: syscallarg(size_t) sigsetsize;
641: } */ *uap = v;
642: linux_sigset_t ls;
643: sigset_t bs;
644: int error = 0;
645:
646: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
647: return (EINVAL);
648:
649: *retval = 0;
650:
651: if (SCARG(uap, oset) != NULL) {
652: /* Fix the return value first if needed */
653: bsd_to_linux_sigset(&p->p_sigmask, &ls);
654: if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
655: return (error);
656: }
657:
658: if (SCARG(uap, set) == NULL)
659: /* Just examine */
660: return (0);
661:
662: if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
663: return (error);
664:
665: linux_to_bsd_sigset(&ls, &bs);
666:
667: (void) splhigh();
668:
669: switch (SCARG(uap, how)) {
670: case LINUX_SIG_BLOCK:
671: p->p_sigmask |= bs & ~sigcantmask;
672: break;
673:
674: case LINUX_SIG_UNBLOCK:
675: p->p_sigmask &= ~bs;
676: break;
677:
678: case LINUX_SIG_SETMASK:
679: p->p_sigmask = bs & ~sigcantmask;
680: break;
681:
682: default:
683: error = EINVAL;
684: break;
685: }
686:
687: (void) spl0();
688:
689: return (error);
690: }
691:
692: /*
693: * The functions below really make no distinction between an int
694: * and [linux_]sigset_t. This is ok for now, but it might break
695: * sometime. Then again, sigset_t is trusted to be an int everywhere
696: * else in the kernel too.
697: */
698: /* ARGSUSED */
699: int
700: linux_sys_siggetmask(p, v, retval)
701: register struct proc *p;
702: void *v;
703: register_t *retval;
704: {
705:
706: bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
707: return (0);
708: }
709:
710: /*
711: * The following three functions fiddle with a process' signal mask.
712: * Convert the signal masks because of the different signal
713: * values for Linux. The need for this is the reason why
714: * they are here, and have not been mapped directly.
715: */
716: int
717: linux_sys_sigsetmask(p, v, retval)
718: register struct proc *p;
719: void *v;
720: register_t *retval;
721: {
722: struct linux_sys_sigsetmask_args /* {
723: syscallarg(linux_old_sigset_t) mask;
724: } */ *uap = v;
725: linux_old_sigset_t mask;
726: sigset_t bsdsig;
727:
728: bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
729:
730: mask = SCARG(uap, mask);
731: bsd_to_linux_old_sigset(&bsdsig, &mask);
732:
733: splhigh();
734: p->p_sigmask = bsdsig & ~sigcantmask;
735: spl0();
736:
737: return (0);
738: }
739:
740: int
741: linux_sys_sigpending(p, v, retval)
742: register struct proc *p;
743: void *v;
744: register_t *retval;
745: {
746: struct linux_sys_sigpending_args /* {
747: syscallarg(linux_old_sigset_t *) mask;
748: } */ *uap = v;
749: sigset_t bs;
750: linux_old_sigset_t ls;
751:
752: bs = p->p_siglist & p->p_sigmask;
753: bsd_to_linux_old_sigset(&bs, &ls);
754:
755: return (copyout(&ls, SCARG(uap, mask), sizeof ls));
756: }
757:
758: int
759: linux_sys_rt_sigpending(p, v, retval)
760: register struct proc *p;
761: void *v;
762: register_t *retval;
763: {
764: struct linux_sys_rt_sigpending_args /* {
765: syscallarg(linux_sigset_t *) set;
766: syscallarg(size_t) sigsetsize;
767: } */ *uap = v;
768: sigset_t bs;
769: linux_sigset_t ls;
770:
771: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
772: return (EINVAL);
773:
774: bs = p->p_siglist & p->p_sigmask;
775: bsd_to_linux_sigset(&bs, &ls);
776:
777: return (copyout(&ls, SCARG(uap, set), sizeof ls));
778: }
779:
780: int
781: linux_sys_sigsuspend(p, v, retval)
782: register struct proc *p;
783: void *v;
784: register_t *retval;
785: {
786: struct linux_sys_sigsuspend_args /* {
787: syscallarg(caddr_t) restart;
788: syscallarg(int) oldmask;
789: syscallarg(int) mask;
790: } */ *uap = v;
791: struct sys_sigsuspend_args sa;
792: linux_old_sigset_t mask = SCARG(uap, mask);
793:
794: linux_old_to_bsd_sigset(&mask, &SCARG(&sa, mask));
795: return (sys_sigsuspend(p, &sa, retval));
796: }
797:
798: int
799: linux_sys_rt_sigsuspend(p, v, retval)
800: register struct proc *p;
801: void *v;
802: register_t *retval;
803: {
804: struct linux_sys_rt_sigsuspend_args /* {
805: syscallarg(sigset_t *) unewset;
806: syscallarg(size_t) sigsetsize;
807: } */ *uap = v;
808: struct sys_sigsuspend_args sa;
809: linux_sigset_t mask;
810: int error;
811:
812: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
813: return (EINVAL);
814:
815: error = copyin(SCARG(uap, unewset), &mask, sizeof mask);
816: if (error)
817: return (error);
818:
819: linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
820: return (sys_sigsuspend(p, &sa, retval));
821: }
822:
823: /*
824: * Linux' sigaltstack structure is just of a different order than BSD's
825: * so just shuffle the fields around and call our version.
826: */
827: int
828: linux_sys_sigaltstack(p, v, retval)
829: register struct proc *p;
830: void *v;
831: register_t *retval;
832: {
833: struct linux_sys_sigaltstack_args /* {
834: syscallarg(const struct linux_sigaltstack *) nss;
835: syscallarg(struct linux_sigaltstack *) oss;
836: } */ *uap = v;
837: struct linux_sigaltstack linux_ss;
838: struct sigaltstack *bsd_nss, *bsd_oss;
839: struct sys_sigaltstack_args sa;
840: int error;
841: caddr_t sg;
842:
843: sg = stackgap_init(p->p_emul);
844:
845: if (SCARG(uap, nss) != NULL) {
846: bsd_nss = stackgap_alloc(&sg, sizeof *bsd_nss);
847:
848: error = copyin(SCARG(uap, nss), &linux_ss, sizeof linux_ss);
849: if (error)
850: return (error);
851:
852: bsd_nss->ss_sp = linux_ss.ss_sp;
853: bsd_nss->ss_size = linux_ss.ss_size;
854: bsd_nss->ss_flags = (linux_ss.ss_flags & LINUX_SS_DISABLE) ?
855: SS_DISABLE : 0;
856:
857: SCARG(&sa, nss) = bsd_nss;
858: } else
859: SCARG(&sa, nss) = NULL;
860:
861: if (SCARG(uap, oss) == NULL) {
862: SCARG(&sa, oss) = NULL;
863: return (sys_sigaltstack(p, &sa, retval));
864: }
865: SCARG(&sa, oss) = bsd_oss = stackgap_alloc(&sg, sizeof *bsd_oss);
866:
867: error = sys_sigaltstack(p, &sa, retval);
868: if (error)
869: return (error);
870:
871: linux_ss.ss_sp = bsd_oss->ss_sp;
872: linux_ss.ss_size = bsd_oss->ss_size;
873: linux_ss.ss_flags = 0;
874: if (bsd_oss->ss_flags & SS_ONSTACK)
875: linux_ss.ss_flags |= LINUX_SS_ONSTACK;
876: if (bsd_oss->ss_flags & SS_DISABLE)
877: linux_ss.ss_flags |= LINUX_SS_DISABLE;
878: return (copyout(&linux_ss, SCARG(uap, oss), sizeof linux_ss));
879: }
880:
881: /*
882: * The deprecated pause(2), which is really just an instance
883: * of sigsuspend(2).
884: */
885: int
886: linux_sys_pause(p, v, retval)
887: register struct proc *p;
888: void *v;
889: register_t *retval;
890: {
891: struct sys_sigsuspend_args bsa;
892:
893: SCARG(&bsa, mask) = p->p_sigmask;
894: return (sys_sigsuspend(p, &bsa, retval));
895: }
896:
897: /*
898: * Once more: only a signal conversion is needed.
899: */
900: int
901: linux_sys_kill(p, v, retval)
902: register struct proc *p;
903: void *v;
904: register_t *retval;
905: {
906: struct linux_sys_kill_args /* {
907: syscallarg(int) pid;
908: syscallarg(int) signum;
909: } */ *uap = v;
910: struct sys_kill_args ka;
911:
912: SCARG(&ka, pid) = SCARG(uap, pid);
913: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
914: return (EINVAL);
915: SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
916: return (sys_kill(p, &ka, retval));
917: }
CVSweb