xref: /freebsd/sys/compat/linux/linux_signal.c (revision 7f8f1d7f7a86fc4a5d0b6f8bd0386d184cf80870)
1c21dee17SSøren Schmidt /*-
29a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
3c21dee17SSøren Schmidt  * All rights reserved.
4c21dee17SSøren Schmidt  *
5c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
6c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
7c21dee17SSøren Schmidt  * are met:
8c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
9c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer
10c21dee17SSøren Schmidt  *    in this position and unchanged.
11c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
12c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
13c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
14c21dee17SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
1521dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
16c21dee17SSøren Schmidt  *
17c21dee17SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18c21dee17SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c21dee17SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20c21dee17SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21c21dee17SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22c21dee17SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c21dee17SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c21dee17SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c21dee17SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26c21dee17SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c21dee17SSøren Schmidt  */
28c21dee17SSøren Schmidt 
2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h>
301e8d246eSNate Lawson __FBSDID("$FreeBSD$");
3116dbc7f2SDavid E. O'Brien 
32c21dee17SSøren Schmidt #include <sys/param.h>
33c21dee17SSøren Schmidt #include <sys/systm.h>
34fb919e4dSMark Murray #include <sys/lock.h>
35fb919e4dSMark Murray #include <sys/mutex.h>
3629ddc19bSAlexander Leidinger #include <sys/sx.h>
37c21dee17SSøren Schmidt #include <sys/proc.h>
38c21dee17SSøren Schmidt #include <sys/signalvar.h>
39206a5d3aSIan Dowse #include <sys/syscallsubr.h>
40fb919e4dSMark Murray #include <sys/sysproto.h>
41c21dee17SSøren Schmidt 
42aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
43aa8b2011SKonstantin Belousov 
44aefce619SRuslan Ermilov #include "opt_compat.h"
45aefce619SRuslan Ermilov 
461997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
474af27623STim J. Robbins #include <machine/../linux32/linux.h>
484af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
491997c537SDavid E. O'Brien #else
501997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
511997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
524af27623STim J. Robbins #endif
53ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
559b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
5681338031SDmitry Chagin #include <compat/linux/linux_misc.h>
5781338031SDmitry Chagin 
5881338031SDmitry Chagin static int	linux_do_tkill(struct thread *td, struct thread *tdt,
5981338031SDmitry Chagin 		    ksiginfo_t *ksi);
60fe4ed1e7SDmitry Chagin static void	sicode_to_lsicode(int si_code, int *lsi_code);
61fe4ed1e7SDmitry Chagin 
629b44bfc5SAlexander Leidinger 
63*7f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
64ba9ef45bSMarcel Moolenaar void
655002a60fSMarcel Moolenaar linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
66956d3333SMarcel Moolenaar {
67d66a5066SPeter Wemm 	int b, l;
68c21dee17SSøren Schmidt 
69956d3333SMarcel Moolenaar 	SIGEMPTYSET(*bss);
70956d3333SMarcel Moolenaar 	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
71956d3333SMarcel Moolenaar 	bss->__bits[1] = lss->__bits[1];
72956d3333SMarcel Moolenaar 	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
73956d3333SMarcel Moolenaar 		if (LINUX_SIGISMEMBER(*lss, l)) {
74956d3333SMarcel Moolenaar 			b = linux_to_bsd_signal[_SIG_IDX(l)];
75956d3333SMarcel Moolenaar 			if (b)
76956d3333SMarcel Moolenaar 				SIGADDSET(*bss, b);
77d66a5066SPeter Wemm 		}
78d66a5066SPeter Wemm 	}
79c21dee17SSøren Schmidt }
80c21dee17SSøren Schmidt 
8179363394SAndrew Gallatin void
825002a60fSMarcel Moolenaar bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
83956d3333SMarcel Moolenaar {
84d66a5066SPeter Wemm 	int b, l;
85c21dee17SSøren Schmidt 
86956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(*lss);
87956d3333SMarcel Moolenaar 	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
88956d3333SMarcel Moolenaar 	lss->__bits[1] = bss->__bits[1];
89956d3333SMarcel Moolenaar 	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
90956d3333SMarcel Moolenaar 		if (SIGISMEMBER(*bss, b)) {
91956d3333SMarcel Moolenaar 			l = bsd_to_linux_signal[_SIG_IDX(b)];
92956d3333SMarcel Moolenaar 			if (l)
93956d3333SMarcel Moolenaar 				LINUX_SIGADDSET(*lss, l);
94d66a5066SPeter Wemm 		}
95d66a5066SPeter Wemm 	}
96c21dee17SSøren Schmidt }
97*7f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
98c21dee17SSøren Schmidt 
99a1ebcbfbSPeter Wemm static void
1005002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
101d66a5066SPeter Wemm {
102956d3333SMarcel Moolenaar 
103956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
1044af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
105d66a5066SPeter Wemm 	bsa->sa_flags = 0;
1068f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
107d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
10806ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
10906ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
11006ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
11106ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
1128f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
113d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
1148f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_RESTART)
115d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
1168f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
117d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
1188f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOMASK)
119d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
120d66a5066SPeter Wemm }
121d66a5066SPeter Wemm 
122a1ebcbfbSPeter Wemm static void
1235002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
124d66a5066SPeter Wemm {
125956d3333SMarcel Moolenaar 
126956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1271997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1284af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1294af27623STim J. Robbins #else
1308f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1314af27623STim J. Robbins #endif
1324af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1338f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
134d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1358f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
13606ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
13706ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
13806ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
13906ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
140d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1418f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
142d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1438f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
144d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1458f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
146d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1478f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
148d66a5066SPeter Wemm }
149c21dee17SSøren Schmidt 
150ba9ef45bSMarcel Moolenaar int
151b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1525002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
15306ebbe77SMarcel Moolenaar {
154206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
155206a5d3aSIan Dowse 	int error, sig;
15606ebbe77SMarcel Moolenaar 
157687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
158956d3333SMarcel Moolenaar 		return (EINVAL);
15906ebbe77SMarcel Moolenaar 
160206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
161956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
162206a5d3aSIan Dowse 		nsa = &act;
163ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
164206a5d3aSIan Dowse 	} else
16506ebbe77SMarcel Moolenaar 		nsa = NULL;
16606ebbe77SMarcel Moolenaar 
167956d3333SMarcel Moolenaar 	if (linux_sig <= LINUX_SIGTBLSZ)
168206a5d3aSIan Dowse 		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
169956d3333SMarcel Moolenaar 	else
170206a5d3aSIan Dowse 		sig = linux_sig;
171956d3333SMarcel Moolenaar 
172206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
17306ebbe77SMarcel Moolenaar 	if (error)
174956d3333SMarcel Moolenaar 		return (error);
17506ebbe77SMarcel Moolenaar 
176ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
177ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
17806ebbe77SMarcel Moolenaar 
179956d3333SMarcel Moolenaar 	return (0);
18006ebbe77SMarcel Moolenaar }
18106ebbe77SMarcel Moolenaar 
182*7f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
183c21dee17SSøren Schmidt int
184b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
185d66a5066SPeter Wemm {
1865002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
187d66a5066SPeter Wemm 	int error;
188d66a5066SPeter Wemm 
189d66a5066SPeter Wemm #ifdef DEBUG
19024593369SJonathan Lemon 	if (ldebug(signal))
19124593369SJonathan Lemon 		printf(ARGS(signal, "%d, %p"),
192b61c60d4SDavid E. O'Brien 		    args->sig, (void *)(uintptr_t)args->handler);
193d66a5066SPeter Wemm #endif
194d66a5066SPeter Wemm 
19506ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
19606ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
197956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
198d66a5066SPeter Wemm 
199b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
2004af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
201d66a5066SPeter Wemm 
202956d3333SMarcel Moolenaar 	return (error);
203d66a5066SPeter Wemm }
204*7f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
205d66a5066SPeter Wemm 
206c21dee17SSøren Schmidt int
207b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
208c21dee17SSøren Schmidt {
2095002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
21006ebbe77SMarcel Moolenaar 	int error;
211c21dee17SSøren Schmidt 
212c21dee17SSøren Schmidt #ifdef DEBUG
21324593369SJonathan Lemon 	if (ldebug(rt_sigaction))
21424593369SJonathan Lemon 		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
21524593369SJonathan Lemon 		    (long)args->sig, (void *)args->act,
2165231fb20SDavid E. O'Brien 		    (void *)args->oact, (long)args->sigsetsize);
217c21dee17SSøren Schmidt #endif
218d66a5066SPeter Wemm 
2195002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
220956d3333SMarcel Moolenaar 		return (EINVAL);
22106ebbe77SMarcel Moolenaar 
222956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2235002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
22406ebbe77SMarcel Moolenaar 		if (error)
225956d3333SMarcel Moolenaar 			return (error);
22606ebbe77SMarcel Moolenaar 	}
22706ebbe77SMarcel Moolenaar 
228b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
22906ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
23006ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
23106ebbe77SMarcel Moolenaar 
232956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2335002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
23406ebbe77SMarcel Moolenaar 	}
23506ebbe77SMarcel Moolenaar 
236956d3333SMarcel Moolenaar 	return (error);
23706ebbe77SMarcel Moolenaar }
23806ebbe77SMarcel Moolenaar 
23906ebbe77SMarcel Moolenaar static int
240b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2415002a60fSMarcel Moolenaar 		     l_sigset_t *old)
24206ebbe77SMarcel Moolenaar {
243fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
244fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
245216af822SJohn Baldwin 	int error;
24606ebbe77SMarcel Moolenaar 
247b40ce416SJulian Elischer 	td->td_retval[0] = 0;
248d66a5066SPeter Wemm 
24919dde5cdSJohn Baldwin 	switch (how) {
25019dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
25119dde5cdSJohn Baldwin 		how = SIG_BLOCK;
25219dde5cdSJohn Baldwin 		break;
25319dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
25419dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
25519dde5cdSJohn Baldwin 		break;
25619dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
25719dde5cdSJohn Baldwin 		how = SIG_SETMASK;
25819dde5cdSJohn Baldwin 		break;
25919dde5cdSJohn Baldwin 	default:
26019dde5cdSJohn Baldwin 		return (EINVAL);
26119dde5cdSJohn Baldwin 	}
26206ebbe77SMarcel Moolenaar 	if (new != NULL) {
263fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
264fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
265fe8cdcaeSJohn Baldwin 	} else
266fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
26719dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2682f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
269fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
27006ebbe77SMarcel Moolenaar 
271956d3333SMarcel Moolenaar 	return (error);
27206ebbe77SMarcel Moolenaar }
27306ebbe77SMarcel Moolenaar 
274*7f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
27506ebbe77SMarcel Moolenaar int
276b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
27706ebbe77SMarcel Moolenaar {
2785002a60fSMarcel Moolenaar 	l_osigset_t mask;
2795002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
28006ebbe77SMarcel Moolenaar 	int error;
28106ebbe77SMarcel Moolenaar 
28206ebbe77SMarcel Moolenaar #ifdef DEBUG
28324593369SJonathan Lemon 	if (ldebug(sigprocmask))
28424593369SJonathan Lemon 		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
28506ebbe77SMarcel Moolenaar #endif
28606ebbe77SMarcel Moolenaar 
28706ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2885002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
28906ebbe77SMarcel Moolenaar 		if (error)
290956d3333SMarcel Moolenaar 			return (error);
291956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
292956d3333SMarcel Moolenaar 		set.__bits[0] = mask;
29306ebbe77SMarcel Moolenaar 	}
29406ebbe77SMarcel Moolenaar 
295b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
296956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
297956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
29806ebbe77SMarcel Moolenaar 
299956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
300956d3333SMarcel Moolenaar 		mask = oset.__bits[0];
3015002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
30206ebbe77SMarcel Moolenaar 	}
30306ebbe77SMarcel Moolenaar 
304956d3333SMarcel Moolenaar 	return (error);
30506ebbe77SMarcel Moolenaar }
306*7f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
30706ebbe77SMarcel Moolenaar 
30806ebbe77SMarcel Moolenaar int
309b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
31006ebbe77SMarcel Moolenaar {
3115002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
31206ebbe77SMarcel Moolenaar 	int error;
31306ebbe77SMarcel Moolenaar 
31406ebbe77SMarcel Moolenaar #ifdef DEBUG
31524593369SJonathan Lemon 	if (ldebug(rt_sigprocmask))
31624593369SJonathan Lemon 		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
31724593369SJonathan Lemon 		    args->how, (void *)args->mask,
3185231fb20SDavid E. O'Brien 		    (void *)args->omask, (long)args->sigsetsize);
31906ebbe77SMarcel Moolenaar #endif
32006ebbe77SMarcel Moolenaar 
3215002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
32206ebbe77SMarcel Moolenaar 		return EINVAL;
32306ebbe77SMarcel Moolenaar 
32406ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3255002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
32606ebbe77SMarcel Moolenaar 		if (error)
327956d3333SMarcel Moolenaar 			return (error);
32806ebbe77SMarcel Moolenaar 	}
32906ebbe77SMarcel Moolenaar 
330b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
331956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
332956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
33306ebbe77SMarcel Moolenaar 
334956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3355002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
33606ebbe77SMarcel Moolenaar 	}
33706ebbe77SMarcel Moolenaar 
338956d3333SMarcel Moolenaar 	return (error);
339c21dee17SSøren Schmidt }
340c21dee17SSøren Schmidt 
341*7f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
342c21dee17SSøren Schmidt int
343b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
344c21dee17SSøren Schmidt {
345b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3465002a60fSMarcel Moolenaar 	l_sigset_t mask;
347956d3333SMarcel Moolenaar 
348c21dee17SSøren Schmidt #ifdef DEBUG
3495002a60fSMarcel Moolenaar 	if (ldebug(sgetmask))
3505002a60fSMarcel Moolenaar 		printf(ARGS(sgetmask, ""));
351c21dee17SSøren Schmidt #endif
352956d3333SMarcel Moolenaar 
353216af822SJohn Baldwin 	PROC_LOCK(p);
3544093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
355216af822SJohn Baldwin 	PROC_UNLOCK(p);
356b40ce416SJulian Elischer 	td->td_retval[0] = mask.__bits[0];
357956d3333SMarcel Moolenaar 	return (0);
358c21dee17SSøren Schmidt }
359c21dee17SSøren Schmidt 
360c21dee17SSøren Schmidt int
361b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
362c21dee17SSøren Schmidt {
363b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3645002a60fSMarcel Moolenaar 	l_sigset_t lset;
365956d3333SMarcel Moolenaar 	sigset_t bset;
366c21dee17SSøren Schmidt 
367c21dee17SSøren Schmidt #ifdef DEBUG
3685002a60fSMarcel Moolenaar 	if (ldebug(ssetmask))
3695002a60fSMarcel Moolenaar 		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
370c21dee17SSøren Schmidt #endif
371d66a5066SPeter Wemm 
372216af822SJohn Baldwin 	PROC_LOCK(p);
3734093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
374b40ce416SJulian Elischer 	td->td_retval[0] = lset.__bits[0];
375956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
376956d3333SMarcel Moolenaar 	lset.__bits[0] = args->mask;
377956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3784093529dSJeff Roberson 	td->td_sigmask = bset;
3794093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3804093529dSJeff Roberson 	signotify(td);
381216af822SJohn Baldwin 	PROC_UNLOCK(p);
382956d3333SMarcel Moolenaar 	return (0);
383c21dee17SSøren Schmidt }
384c21dee17SSøren Schmidt 
385c21dee17SSøren Schmidt int
386b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
387c21dee17SSøren Schmidt {
388b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
389956d3333SMarcel Moolenaar 	sigset_t bset;
3905002a60fSMarcel Moolenaar 	l_sigset_t lset;
3915002a60fSMarcel Moolenaar 	l_osigset_t mask;
392c21dee17SSøren Schmidt 
393c21dee17SSøren Schmidt #ifdef DEBUG
39424593369SJonathan Lemon 	if (ldebug(sigpending))
39524593369SJonathan Lemon 		printf(ARGS(sigpending, "*"));
396c21dee17SSøren Schmidt #endif
397956d3333SMarcel Moolenaar 
398216af822SJohn Baldwin 	PROC_LOCK(p);
3991d9c5696SJuli Mallett 	bset = p->p_siglist;
4004093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
4014093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
402216af822SJohn Baldwin 	PROC_UNLOCK(p);
4039d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
404956d3333SMarcel Moolenaar 	mask = lset.__bits[0];
405956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
406c21dee17SSøren Schmidt }
407*7f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
40817138b61SAlexander Leidinger 
40917138b61SAlexander Leidinger /*
41017138b61SAlexander Leidinger  * MPSAFE
41117138b61SAlexander Leidinger  */
41217138b61SAlexander Leidinger int
41317138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
41417138b61SAlexander Leidinger {
41517138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
41617138b61SAlexander Leidinger 	sigset_t bset;
41717138b61SAlexander Leidinger 	l_sigset_t lset;
41817138b61SAlexander Leidinger 
41917138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
42017138b61SAlexander Leidinger 		return EINVAL;
42117138b61SAlexander Leidinger 		/* NOT REACHED */
42217138b61SAlexander Leidinger 
42317138b61SAlexander Leidinger #ifdef DEBUG
42417138b61SAlexander Leidinger 	if (ldebug(rt_sigpending))
42517138b61SAlexander Leidinger 		printf(ARGS(rt_sigpending, "*"));
42617138b61SAlexander Leidinger #endif
42717138b61SAlexander Leidinger 
42817138b61SAlexander Leidinger 	PROC_LOCK(p);
42917138b61SAlexander Leidinger 	bset = p->p_siglist;
43017138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
43117138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
43217138b61SAlexander Leidinger 	PROC_UNLOCK(p);
43317138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
43417138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
43517138b61SAlexander Leidinger }
436c21dee17SSøren Schmidt 
437c9447c75SAlexander Leidinger /*
438c9447c75SAlexander Leidinger  * MPSAFE
439c9447c75SAlexander Leidinger  */
440c9447c75SAlexander Leidinger int
441c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
442c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
443c9447c75SAlexander Leidinger {
444f3481dd9SDmitry Chagin 	int error, sig;
445c9447c75SAlexander Leidinger 	l_timeval ltv;
446c9447c75SAlexander Leidinger 	struct timeval tv;
447c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
448c9447c75SAlexander Leidinger 	l_sigset_t lset;
449c9447c75SAlexander Leidinger 	sigset_t bset;
450c9447c75SAlexander Leidinger 	l_siginfo_t linfo;
451c9447c75SAlexander Leidinger 	ksiginfo_t info;
452c9447c75SAlexander Leidinger 
453c9447c75SAlexander Leidinger #ifdef DEBUG
454c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
455c9447c75SAlexander Leidinger 		printf(ARGS(rt_sigtimedwait, "*"));
456c9447c75SAlexander Leidinger #endif
457c9447c75SAlexander Leidinger 	if (args->sigsetsize != sizeof(l_sigset_t))
458c9447c75SAlexander Leidinger 		return (EINVAL);
459c9447c75SAlexander Leidinger 
460c9447c75SAlexander Leidinger 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
461c9447c75SAlexander Leidinger 		return (error);
462c9447c75SAlexander Leidinger 	linux_to_bsd_sigset(&lset, &bset);
463c9447c75SAlexander Leidinger 
464c9447c75SAlexander Leidinger 	tsa = NULL;
465c9447c75SAlexander Leidinger 	if (args->timeout) {
466c9447c75SAlexander Leidinger 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
467c9447c75SAlexander Leidinger 			return (error);
468c9447c75SAlexander Leidinger #ifdef DEBUG
469c9447c75SAlexander Leidinger 		if (ldebug(rt_sigtimedwait))
4708c50c562SDmitry Chagin 			printf(LMSG("linux_rt_sigtimedwait: "
4718c50c562SDmitry Chagin 			    "incoming timeout (%d/%d)\n"),
472c9447c75SAlexander Leidinger 			    ltv.tv_sec, ltv.tv_usec);
473c9447c75SAlexander Leidinger #endif
474c9447c75SAlexander Leidinger 		tv.tv_sec = (long)ltv.tv_sec;
475c9447c75SAlexander Leidinger 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
476c9447c75SAlexander Leidinger 		if (itimerfix(&tv)) {
477c9447c75SAlexander Leidinger 			/*
478c9447c75SAlexander Leidinger 			 * The timeout was invalid. Convert it to something
479c9447c75SAlexander Leidinger 			 * valid that will act as it does under Linux.
480c9447c75SAlexander Leidinger 			 */
481c9447c75SAlexander Leidinger 			tv.tv_sec += tv.tv_usec / 1000000;
482c9447c75SAlexander Leidinger 			tv.tv_usec %= 1000000;
483c9447c75SAlexander Leidinger 			if (tv.tv_usec < 0) {
484c9447c75SAlexander Leidinger 				tv.tv_sec -= 1;
485c9447c75SAlexander Leidinger 				tv.tv_usec += 1000000;
486c9447c75SAlexander Leidinger 			}
487c9447c75SAlexander Leidinger 			if (tv.tv_sec < 0)
488c9447c75SAlexander Leidinger 				timevalclear(&tv);
489c9447c75SAlexander Leidinger #ifdef DEBUG
490c9447c75SAlexander Leidinger 			if (ldebug(rt_sigtimedwait))
4918c50c562SDmitry Chagin 				printf(LMSG("linux_rt_sigtimedwait: "
4928c50c562SDmitry Chagin 				    "converted timeout (%jd/%ld)\n"),
49359038483SXin LI 				    (intmax_t)tv.tv_sec, tv.tv_usec);
494c9447c75SAlexander Leidinger #endif
495c9447c75SAlexander Leidinger 		}
496c9447c75SAlexander Leidinger 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
497c9447c75SAlexander Leidinger 		tsa = &ts;
498c9447c75SAlexander Leidinger 	}
499c9447c75SAlexander Leidinger 	error = kern_sigtimedwait(td, bset, &info, tsa);
500c9447c75SAlexander Leidinger #ifdef DEBUG
501c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
5028c50c562SDmitry Chagin 		printf(LMSG("linux_rt_sigtimedwait: "
5038c50c562SDmitry Chagin 		    "sigtimedwait returning (%d)\n"), error);
504c9447c75SAlexander Leidinger #endif
505c9447c75SAlexander Leidinger 	if (error)
506c9447c75SAlexander Leidinger 		return (error);
507c9447c75SAlexander Leidinger 
508f3481dd9SDmitry Chagin 	sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
509f3481dd9SDmitry Chagin 
510c9447c75SAlexander Leidinger 	if (args->ptr) {
511c9447c75SAlexander Leidinger 		memset(&linfo, 0, sizeof(linfo));
512f3481dd9SDmitry Chagin 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
513c9447c75SAlexander Leidinger 		error = copyout(&linfo, args->ptr, sizeof(linfo));
514c9447c75SAlexander Leidinger 	}
515f3481dd9SDmitry Chagin 	if (error == 0)
516f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
517c9447c75SAlexander Leidinger 
518c9447c75SAlexander Leidinger 	return (error);
519c9447c75SAlexander Leidinger }
520c9447c75SAlexander Leidinger 
521c21dee17SSøren Schmidt int
522b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
523c21dee17SSøren Schmidt {
524ef04503dSPeter Wemm 	struct kill_args /* {
525c21dee17SSøren Schmidt 	    int pid;
526c21dee17SSøren Schmidt 	    int signum;
527ef04503dSPeter Wemm 	} */ tmp;
528c21dee17SSøren Schmidt 
529c21dee17SSøren Schmidt #ifdef DEBUG
53024593369SJonathan Lemon 	if (ldebug(kill))
53124593369SJonathan Lemon 		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
532c21dee17SSøren Schmidt #endif
533956d3333SMarcel Moolenaar 
534956d3333SMarcel Moolenaar 	/*
535956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
536956d3333SMarcel Moolenaar 	 */
53764742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5389a6a64d3SDmitry Chagin 		return (EINVAL);
539956d3333SMarcel Moolenaar 
540956d3333SMarcel Moolenaar 	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
541956d3333SMarcel Moolenaar 		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
542956d3333SMarcel Moolenaar 	else
543956d3333SMarcel Moolenaar 		tmp.signum = args->signum;
544956d3333SMarcel Moolenaar 
545c21dee17SSøren Schmidt 	tmp.pid = args->pid;
5468451d0ddSKip Macy 	return (sys_kill(td, &tmp));
547c21dee17SSøren Schmidt }
5489b44bfc5SAlexander Leidinger 
549aa8b2011SKonstantin Belousov static int
55081338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
551aa8b2011SKonstantin Belousov {
552aa8b2011SKonstantin Belousov 	struct proc *p;
553aa8b2011SKonstantin Belousov 	int error;
554aa8b2011SKonstantin Belousov 
55581338031SDmitry Chagin 	p = tdt->td_proc;
55681338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
55781338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
55814961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
55981338031SDmitry Chagin 
56081338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
56181338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
562aa8b2011SKonstantin Belousov 		goto out;
563aa8b2011SKonstantin Belousov 
56481338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
565aa8b2011SKonstantin Belousov 
566aa8b2011SKonstantin Belousov out:
567aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
568aa8b2011SKonstantin Belousov 	return (error);
569aa8b2011SKonstantin Belousov }
570aa8b2011SKonstantin Belousov 
5719b44bfc5SAlexander Leidinger int
5729b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5739b44bfc5SAlexander Leidinger {
57481338031SDmitry Chagin 	struct thread *tdt;
57581338031SDmitry Chagin 	ksiginfo_t ksi;
57681338031SDmitry Chagin 	int sig;
5779b44bfc5SAlexander Leidinger 
5789b44bfc5SAlexander Leidinger #ifdef DEBUG
5799b44bfc5SAlexander Leidinger 	if (ldebug(tgkill))
58081338031SDmitry Chagin 		printf(ARGS(tgkill, "%d, %d, %d"),
58181338031SDmitry Chagin 		    args->tgid, args->pid, args->sig);
5829b44bfc5SAlexander Leidinger #endif
58381338031SDmitry Chagin 
584aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
585aa8b2011SKonstantin Belousov 		return (EINVAL);
5869b44bfc5SAlexander Leidinger 
58781338031SDmitry Chagin 	/*
58881338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
58981338031SDmitry Chagin 	 */
59081338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
59181338031SDmitry Chagin 		return (EINVAL);
59281338031SDmitry Chagin 
59381338031SDmitry Chagin 	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
59481338031SDmitry Chagin 		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
59581338031SDmitry Chagin 	else
59681338031SDmitry Chagin 		sig = args->sig;
59781338031SDmitry Chagin 
59881338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
59981338031SDmitry Chagin 	if (tdt == NULL)
60081338031SDmitry Chagin 		return (ESRCH);
60181338031SDmitry Chagin 
60281338031SDmitry Chagin 	ksiginfo_init(&ksi);
60381338031SDmitry Chagin 	ksi.ksi_signo = sig;
604fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
60581338031SDmitry Chagin 	ksi.ksi_errno = 0;
60681338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
60781338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
60881338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
6099b44bfc5SAlexander Leidinger }
6109b44bfc5SAlexander Leidinger 
61181338031SDmitry Chagin /*
61281338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
61381338031SDmitry Chagin  */
6149b44bfc5SAlexander Leidinger int
6159b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
6169b44bfc5SAlexander Leidinger {
61781338031SDmitry Chagin 	struct thread *tdt;
61881338031SDmitry Chagin 	ksiginfo_t ksi;
61981338031SDmitry Chagin 	int sig;
62081338031SDmitry Chagin 
6219b44bfc5SAlexander Leidinger #ifdef DEBUG
6229b44bfc5SAlexander Leidinger 	if (ldebug(tkill))
6239b44bfc5SAlexander Leidinger 		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
6249b44bfc5SAlexander Leidinger #endif
625aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
626aa8b2011SKonstantin Belousov 		return (EINVAL);
6279b44bfc5SAlexander Leidinger 
62881338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
62981338031SDmitry Chagin 		return (EINVAL);
63081338031SDmitry Chagin 
63181338031SDmitry Chagin 	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
63281338031SDmitry Chagin 		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
63381338031SDmitry Chagin 	else
63481338031SDmitry Chagin 		sig = args->sig;
63581338031SDmitry Chagin 
63681338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
63781338031SDmitry Chagin 	if (tdt == NULL)
63881338031SDmitry Chagin 		return (ESRCH);
63981338031SDmitry Chagin 
64081338031SDmitry Chagin 	ksiginfo_init(&ksi);
64181338031SDmitry Chagin 	ksi.ksi_signo = sig;
642fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
64381338031SDmitry Chagin 	ksi.ksi_errno = 0;
64481338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
64581338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
64681338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
647aa8b2011SKonstantin Belousov }
648aa8b2011SKonstantin Belousov 
649aa8b2011SKonstantin Belousov void
650fe4ed1e7SDmitry Chagin ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
651aa8b2011SKonstantin Belousov {
652aa8b2011SKonstantin Belousov 
653fe4ed1e7SDmitry Chagin 	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
654fe4ed1e7SDmitry Chagin }
655aa8b2011SKonstantin Belousov 
656fe4ed1e7SDmitry Chagin static void
657fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
658fe4ed1e7SDmitry Chagin {
659fe4ed1e7SDmitry Chagin 
660fe4ed1e7SDmitry Chagin 	switch (si_code) {
661fe4ed1e7SDmitry Chagin 	case SI_USER:
662fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
663fe4ed1e7SDmitry Chagin 		break;
664fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
665fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
666fe4ed1e7SDmitry Chagin 		break;
667fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
668fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
669fe4ed1e7SDmitry Chagin 		break;
670fe4ed1e7SDmitry Chagin 	case SI_TIMER:
671fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
672fe4ed1e7SDmitry Chagin 		break;
673fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
674fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
675fe4ed1e7SDmitry Chagin 		break;
676fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
677fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
678fe4ed1e7SDmitry Chagin 		break;
679fe4ed1e7SDmitry Chagin 	case SI_LWP:
680fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
681fe4ed1e7SDmitry Chagin 		break;
682fe4ed1e7SDmitry Chagin 	default:
683fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
684fe4ed1e7SDmitry Chagin 		break;
685fe4ed1e7SDmitry Chagin 	}
686fe4ed1e7SDmitry Chagin }
687fe4ed1e7SDmitry Chagin 
688fe4ed1e7SDmitry Chagin void
689fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
690fe4ed1e7SDmitry Chagin {
691fe4ed1e7SDmitry Chagin 
692fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
693fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
694fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
695fe4ed1e7SDmitry Chagin 
696fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
697fe4ed1e7SDmitry Chagin 	case SI_LWP:
698fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
699fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
700fe4ed1e7SDmitry Chagin 		break;
701fe4ed1e7SDmitry Chagin 
702fe4ed1e7SDmitry Chagin 	case SI_TIMER:
703fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
704fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
705fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
706fe4ed1e7SDmitry Chagin 		break;
707fe4ed1e7SDmitry Chagin 
708fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
709fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
710fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
711fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
712fe4ed1e7SDmitry Chagin 		break;
713fe4ed1e7SDmitry Chagin 
714fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
715fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
716fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
717fe4ed1e7SDmitry Chagin 		break;
718fe4ed1e7SDmitry Chagin 
719fe4ed1e7SDmitry Chagin 	default:
720aa8b2011SKonstantin Belousov 		switch (sig) {
721aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
722aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
723fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
724aa8b2011SKonstantin Belousov 			break;
725fe4ed1e7SDmitry Chagin 
726aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
727fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
728fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
729fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
730fe4ed1e7SDmitry Chagin 
731fe4ed1e7SDmitry Chagin 			if (si->si_code == CLD_STOPPED)
732fe4ed1e7SDmitry Chagin 				lsi->lsi_status = BSD_TO_LINUX_SIGNAL(si->si_status);
733fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
734fe4ed1e7SDmitry Chagin 				lsi->lsi_status = BSD_TO_LINUX_SIGNAL(SIGCONT);
735fe4ed1e7SDmitry Chagin 			else
736fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
737aa8b2011SKonstantin Belousov 			break;
738fe4ed1e7SDmitry Chagin 
739aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
740aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
741aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
742aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
743fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
744aa8b2011SKonstantin Belousov 			break;
745fe4ed1e7SDmitry Chagin 
746aa8b2011SKonstantin Belousov 		default:
747fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
748fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
749fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
750fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
751fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
752fe4ed1e7SDmitry Chagin 			}
753aa8b2011SKonstantin Belousov 			break;
754aa8b2011SKonstantin Belousov 		}
755fe4ed1e7SDmitry Chagin 		break;
75609d6cb0aSDmitry Chagin 	}
7579b44bfc5SAlexander Leidinger }
7587ac9766dSDmitry Chagin 
7597ac9766dSDmitry Chagin void
7607ac9766dSDmitry Chagin lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
7617ac9766dSDmitry Chagin {
7627ac9766dSDmitry Chagin 
7637ac9766dSDmitry Chagin 	ksi->ksi_signo = sig;
7647ac9766dSDmitry Chagin 	ksi->ksi_code = lsi->lsi_code;	/* XXX. Convert. */
7657ac9766dSDmitry Chagin 	ksi->ksi_pid = lsi->lsi_pid;
7667ac9766dSDmitry Chagin 	ksi->ksi_uid = lsi->lsi_uid;
7677ac9766dSDmitry Chagin 	ksi->ksi_status = lsi->lsi_status;
7687ac9766dSDmitry Chagin 	ksi->ksi_addr = PTRIN(lsi->lsi_addr);
7697ac9766dSDmitry Chagin 	ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
7707ac9766dSDmitry Chagin }
7717ac9766dSDmitry Chagin 
7727ac9766dSDmitry Chagin int
7737ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7747ac9766dSDmitry Chagin {
7757ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7767ac9766dSDmitry Chagin 	struct proc *p;
7777ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7787ac9766dSDmitry Chagin 	int error;
7797ac9766dSDmitry Chagin 	int sig;
7807ac9766dSDmitry Chagin 
7817ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7827ac9766dSDmitry Chagin 		return (EINVAL);
7837ac9766dSDmitry Chagin 
7847ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7857ac9766dSDmitry Chagin 	if (error != 0)
7867ac9766dSDmitry Chagin 		return (error);
7877ac9766dSDmitry Chagin 
7887ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7897ac9766dSDmitry Chagin 		return (EPERM);
7907ac9766dSDmitry Chagin 
7917ac9766dSDmitry Chagin 	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
7927ac9766dSDmitry Chagin 		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
7937ac9766dSDmitry Chagin 	else
7947ac9766dSDmitry Chagin 		sig = args->sig;
7957ac9766dSDmitry Chagin 
7967ac9766dSDmitry Chagin 	error = ESRCH;
7977ac9766dSDmitry Chagin 	if ((p = pfind(args->pid)) != NULL ||
7987ac9766dSDmitry Chagin 	    (p = zpfind(args->pid)) != NULL) {
7997ac9766dSDmitry Chagin 		error = p_cansignal(td, p, sig);
8007ac9766dSDmitry Chagin 		if (error != 0) {
8017ac9766dSDmitry Chagin 			PROC_UNLOCK(p);
8027ac9766dSDmitry Chagin 			return (error);
8037ac9766dSDmitry Chagin 		}
8047ac9766dSDmitry Chagin 
8057ac9766dSDmitry Chagin 		ksiginfo_init(&ksi);
8067ac9766dSDmitry Chagin 		lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
8077ac9766dSDmitry Chagin 		error = tdsendsignal(p, NULL, sig, &ksi);
8087ac9766dSDmitry Chagin 		PROC_UNLOCK(p);
8097ac9766dSDmitry Chagin 	}
8107ac9766dSDmitry Chagin 
8117ac9766dSDmitry Chagin 	return (error);
8127ac9766dSDmitry Chagin }
813