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
linux_old_to_bsd_sigset(lss,bss)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
bsd_to_linux_old_sigset(bss,lss)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
linux_old_extra_to_bsd_sigset(lss,extra,bss)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
bsd_to_linux_old_extra_sigset(bss,lss,extra)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
linux_to_bsd_sigset(lss,bss)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
bsd_to_linux_sigset(bss,lss)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
linux_old_to_bsd_sigaction(lsa,bsa)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
bsd_to_linux_old_sigaction(bsa,lsa)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
linux_to_bsd_sigaction(lsa,bsa)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
bsd_to_linux_sigaction(bsa,lsa)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
linux_to_bsd_signal(int linuxsig,int * bsdsig)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
bsd_to_linux_signal(int bsdsig,int * linuxsig)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
linux_sys_sigaction(p,v,retval)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
linux_sys_rt_sigaction(p,v,retval)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
linux_sys_signal(p,v,retval)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
linux_sys_sigprocmask(p,v,retval)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
linux_sys_rt_sigprocmask(p,v,retval)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
linux_sys_siggetmask(p,v,retval)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
linux_sys_sigsetmask(p,v,retval)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
linux_sys_sigpending(p,v,retval)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
linux_sys_rt_sigpending(p,v,retval)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
linux_sys_sigsuspend(p,v,retval)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
linux_sys_rt_sigsuspend(p,v,retval)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
linux_sys_sigaltstack(p,v,retval)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
linux_sys_pause(p,v,retval)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
linux_sys_kill(p,v,retval)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 }
918