xref: /freebsd/sys/compat/linux/linux_signal.c (revision 3eaf271d3c0e4fa18b74971a71c950fd43fa4189)
1c21dee17SSøren Schmidt /*-
20ba1b365SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni  *
49a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
5c21dee17SSøren Schmidt  * All rights reserved.
6c21dee17SSøren Schmidt  *
7c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
8c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
9c21dee17SSøren Schmidt  * are met:
10c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
110ba1b365SEd Maste  *    notice, this list of conditions and the following disclaimer.
12c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
13c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
14c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
15c21dee17SSøren Schmidt  *
160ba1b365SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170ba1b365SEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180ba1b365SEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190ba1b365SEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200ba1b365SEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210ba1b365SEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220ba1b365SEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230ba1b365SEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240ba1b365SEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250ba1b365SEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260ba1b365SEd Maste  * 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
539c1045ffSDmitry Chagin #include <compat/linux/linux_mib.h>
54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
550f8dab45SDmitry Chagin #include <compat/linux/linux_timer.h>
56ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
579b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
5881338031SDmitry Chagin #include <compat/linux/linux_misc.h>
5981338031SDmitry Chagin 
6081338031SDmitry Chagin static int	linux_do_tkill(struct thread *td, struct thread *tdt,
6181338031SDmitry Chagin 		    ksiginfo_t *ksi);
62fe4ed1e7SDmitry Chagin static void	sicode_to_lsicode(int si_code, int *lsi_code);
63db4a1f33SDmitry Chagin static int	linux_common_rt_sigtimedwait(struct thread *,
64db4a1f33SDmitry Chagin 		    l_sigset_t *, struct timespec *, l_siginfo_t *,
65db4a1f33SDmitry Chagin 		    l_size_t);
66fe4ed1e7SDmitry Chagin 
67a1ebcbfbSPeter Wemm static void
685002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
69d66a5066SPeter Wemm {
70d5629eb2SEdward Tomasz Napierala 	unsigned long flags;
71956d3333SMarcel Moolenaar 
72956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
734af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
74d66a5066SPeter Wemm 	bsa->sa_flags = 0;
75d5629eb2SEdward Tomasz Napierala 
76d5629eb2SEdward Tomasz Napierala 	flags = lsa->lsa_flags;
77d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
78d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDSTOP;
79d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
80d5629eb2SEdward Tomasz Napierala 	}
81d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
82d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDWAIT;
8306ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
84d5629eb2SEdward Tomasz Napierala 	}
85d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
86d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_SIGINFO;
8706ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
88d5629eb2SEdward Tomasz Napierala #ifdef notyet
89d5629eb2SEdward Tomasz Napierala 		/*
90d5629eb2SEdward Tomasz Napierala 		 * XXX: We seem to be missing code to convert
91d5629eb2SEdward Tomasz Napierala 		 *      some of the fields in ucontext_t.
92d5629eb2SEdward Tomasz Napierala 		 */
93d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread,
94d5629eb2SEdward Tomasz Napierala 		    "partially unsupported sigaction flag SA_SIGINFO");
95d5629eb2SEdward Tomasz Napierala #endif
96d5629eb2SEdward Tomasz Napierala 	}
97d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTORER) {
98d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTORER;
99*3eaf271dSEdward Tomasz Napierala 		/*
100*3eaf271dSEdward Tomasz Napierala 		 * We ignore the lsa_restorer and always use our own signal
101*3eaf271dSEdward Tomasz Napierala 		 * trampoline instead.  It looks like SA_RESTORER is obsolete
102*3eaf271dSEdward Tomasz Napierala 		 * in Linux too - it doesn't seem to be used at all on arm64.
103*3eaf271dSEdward Tomasz Napierala 		 * In any case: see Linux sigreturn(2).
104*3eaf271dSEdward Tomasz Napierala 		 */
105d5629eb2SEdward Tomasz Napierala 	}
106d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
107d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONSTACK;
108d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
109d5629eb2SEdward Tomasz Napierala 	}
110d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
111d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTART;
112d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
113d5629eb2SEdward Tomasz Napierala 	}
1149bc42c18SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
1159bc42c18SEdward Tomasz Napierala 		flags &= ~LINUX_SA_INTERRUPT;
1169bc42c18SEdward Tomasz Napierala 		/* Documented to be a "historical no-op". */
1179bc42c18SEdward Tomasz Napierala 	}
118d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
119d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONESHOT;
120d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
121d5629eb2SEdward Tomasz Napierala 	}
122d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
123d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOMASK;
124d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
125d66a5066SPeter Wemm 	}
126d66a5066SPeter Wemm 
127d5629eb2SEdward Tomasz Napierala 	if (flags != 0)
128d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
129d5629eb2SEdward Tomasz Napierala }
130d5629eb2SEdward Tomasz Napierala 
131a1ebcbfbSPeter Wemm static void
1325002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
133d66a5066SPeter Wemm {
134956d3333SMarcel Moolenaar 
135956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1361997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1374af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1384af27623STim J. Robbins #else
1398f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1404af27623STim J. Robbins #endif
1414af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1428f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
143d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1448f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
14506ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
14606ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
14706ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
14806ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
149d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1508f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
151d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1528f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
153d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1548f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
155d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1568f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
157d66a5066SPeter Wemm }
158c21dee17SSøren Schmidt 
159ba9ef45bSMarcel Moolenaar int
160b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1615002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
16206ebbe77SMarcel Moolenaar {
163206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
164206a5d3aSIan Dowse 	int error, sig;
16506ebbe77SMarcel Moolenaar 
166687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
167956d3333SMarcel Moolenaar 		return (EINVAL);
16806ebbe77SMarcel Moolenaar 
169206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
170956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
171206a5d3aSIan Dowse 		nsa = &act;
172ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
173206a5d3aSIan Dowse 	} else
17406ebbe77SMarcel Moolenaar 		nsa = NULL;
1754ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(linux_sig);
176956d3333SMarcel Moolenaar 
177206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
17806ebbe77SMarcel Moolenaar 	if (error)
179956d3333SMarcel Moolenaar 		return (error);
18006ebbe77SMarcel Moolenaar 
181ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
182ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
18306ebbe77SMarcel Moolenaar 
184956d3333SMarcel Moolenaar 	return (0);
18506ebbe77SMarcel Moolenaar }
18606ebbe77SMarcel Moolenaar 
1877f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
188c21dee17SSøren Schmidt int
189b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
190d66a5066SPeter Wemm {
1915002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
192d66a5066SPeter Wemm 	int error;
193d66a5066SPeter Wemm 
19406ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
19506ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
196956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
197d66a5066SPeter Wemm 
198b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1994af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
200d66a5066SPeter Wemm 
201956d3333SMarcel Moolenaar 	return (error);
202d66a5066SPeter Wemm }
2037f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
204d66a5066SPeter Wemm 
205c21dee17SSøren Schmidt int
206b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
207c21dee17SSøren Schmidt {
2085002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
20906ebbe77SMarcel Moolenaar 	int error;
210c21dee17SSøren Schmidt 
2115002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
212956d3333SMarcel Moolenaar 		return (EINVAL);
21306ebbe77SMarcel Moolenaar 
214956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2155002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21606ebbe77SMarcel Moolenaar 		if (error)
217956d3333SMarcel Moolenaar 			return (error);
21806ebbe77SMarcel Moolenaar 	}
21906ebbe77SMarcel Moolenaar 
220b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
22106ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
22206ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
22306ebbe77SMarcel Moolenaar 
224956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2255002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22606ebbe77SMarcel Moolenaar 	}
22706ebbe77SMarcel Moolenaar 
228956d3333SMarcel Moolenaar 	return (error);
22906ebbe77SMarcel Moolenaar }
23006ebbe77SMarcel Moolenaar 
23106ebbe77SMarcel Moolenaar static int
232b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2335002a60fSMarcel Moolenaar 		     l_sigset_t *old)
23406ebbe77SMarcel Moolenaar {
235fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
236fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
237216af822SJohn Baldwin 	int error;
23806ebbe77SMarcel Moolenaar 
239b40ce416SJulian Elischer 	td->td_retval[0] = 0;
240d66a5066SPeter Wemm 
24119dde5cdSJohn Baldwin 	switch (how) {
24219dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
24319dde5cdSJohn Baldwin 		how = SIG_BLOCK;
24419dde5cdSJohn Baldwin 		break;
24519dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
24619dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
24719dde5cdSJohn Baldwin 		break;
24819dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
24919dde5cdSJohn Baldwin 		how = SIG_SETMASK;
25019dde5cdSJohn Baldwin 		break;
25119dde5cdSJohn Baldwin 	default:
25219dde5cdSJohn Baldwin 		return (EINVAL);
25319dde5cdSJohn Baldwin 	}
25406ebbe77SMarcel Moolenaar 	if (new != NULL) {
255fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
256fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
257fe8cdcaeSJohn Baldwin 	} else
258fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
25919dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2602f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
261fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
26206ebbe77SMarcel Moolenaar 
263956d3333SMarcel Moolenaar 	return (error);
26406ebbe77SMarcel Moolenaar }
26506ebbe77SMarcel Moolenaar 
2667f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
26706ebbe77SMarcel Moolenaar int
268b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
26906ebbe77SMarcel Moolenaar {
2705002a60fSMarcel Moolenaar 	l_osigset_t mask;
2715002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
27206ebbe77SMarcel Moolenaar 	int error;
27306ebbe77SMarcel Moolenaar 
27406ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2755002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
27606ebbe77SMarcel Moolenaar 		if (error)
277956d3333SMarcel Moolenaar 			return (error);
278956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
2794ab7403bSDmitry Chagin 		set.__mask = mask;
28006ebbe77SMarcel Moolenaar 	}
28106ebbe77SMarcel Moolenaar 
282b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
283956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
284956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
28506ebbe77SMarcel Moolenaar 
286956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
2874ab7403bSDmitry Chagin 		mask = oset.__mask;
2885002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
28906ebbe77SMarcel Moolenaar 	}
29006ebbe77SMarcel Moolenaar 
291956d3333SMarcel Moolenaar 	return (error);
29206ebbe77SMarcel Moolenaar }
2937f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
29406ebbe77SMarcel Moolenaar 
29506ebbe77SMarcel Moolenaar int
296b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
29706ebbe77SMarcel Moolenaar {
2985002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
29906ebbe77SMarcel Moolenaar 	int error;
30006ebbe77SMarcel Moolenaar 
3015002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
302340f4a8dSEd Maste 		return (EINVAL);
30306ebbe77SMarcel Moolenaar 
30406ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3055002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
30606ebbe77SMarcel Moolenaar 		if (error)
307956d3333SMarcel Moolenaar 			return (error);
30806ebbe77SMarcel Moolenaar 	}
30906ebbe77SMarcel Moolenaar 
310b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
311956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
312956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
31306ebbe77SMarcel Moolenaar 
314956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3155002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
31606ebbe77SMarcel Moolenaar 	}
31706ebbe77SMarcel Moolenaar 
318956d3333SMarcel Moolenaar 	return (error);
319c21dee17SSøren Schmidt }
320c21dee17SSøren Schmidt 
3217f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
322c21dee17SSøren Schmidt int
323b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
324c21dee17SSøren Schmidt {
325b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3265002a60fSMarcel Moolenaar 	l_sigset_t mask;
327956d3333SMarcel Moolenaar 
328216af822SJohn Baldwin 	PROC_LOCK(p);
3294093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
330216af822SJohn Baldwin 	PROC_UNLOCK(p);
3314ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
332956d3333SMarcel Moolenaar 	return (0);
333c21dee17SSøren Schmidt }
334c21dee17SSøren Schmidt 
335c21dee17SSøren Schmidt int
336b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
337c21dee17SSøren Schmidt {
338b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3395002a60fSMarcel Moolenaar 	l_sigset_t lset;
340956d3333SMarcel Moolenaar 	sigset_t bset;
341c21dee17SSøren Schmidt 
342216af822SJohn Baldwin 	PROC_LOCK(p);
3434093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3444ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
345956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3464ab7403bSDmitry Chagin 	lset.__mask = args->mask;
347956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3484093529dSJeff Roberson 	td->td_sigmask = bset;
3494093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3504093529dSJeff Roberson 	signotify(td);
351216af822SJohn Baldwin 	PROC_UNLOCK(p);
352956d3333SMarcel Moolenaar 	return (0);
353c21dee17SSøren Schmidt }
354c21dee17SSøren Schmidt 
355c21dee17SSøren Schmidt int
356b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
357c21dee17SSøren Schmidt {
358b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
359956d3333SMarcel Moolenaar 	sigset_t bset;
3605002a60fSMarcel Moolenaar 	l_sigset_t lset;
3615002a60fSMarcel Moolenaar 	l_osigset_t mask;
362c21dee17SSøren Schmidt 
363216af822SJohn Baldwin 	PROC_LOCK(p);
3641d9c5696SJuli Mallett 	bset = p->p_siglist;
3654093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3664093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
367216af822SJohn Baldwin 	PROC_UNLOCK(p);
3689d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
3694ab7403bSDmitry Chagin 	mask = lset.__mask;
370956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
371c21dee17SSøren Schmidt }
3727f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
37317138b61SAlexander Leidinger 
37417138b61SAlexander Leidinger /*
37517138b61SAlexander Leidinger  * MPSAFE
37617138b61SAlexander Leidinger  */
37717138b61SAlexander Leidinger int
37817138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
37917138b61SAlexander Leidinger {
38017138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
38117138b61SAlexander Leidinger 	sigset_t bset;
38217138b61SAlexander Leidinger 	l_sigset_t lset;
38317138b61SAlexander Leidinger 
38417138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
385340f4a8dSEd Maste 		return (EINVAL);
38617138b61SAlexander Leidinger 		/* NOT REACHED */
38717138b61SAlexander Leidinger 
38817138b61SAlexander Leidinger 	PROC_LOCK(p);
38917138b61SAlexander Leidinger 	bset = p->p_siglist;
39017138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
39117138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
39217138b61SAlexander Leidinger 	PROC_UNLOCK(p);
39317138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
39417138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
39517138b61SAlexander Leidinger }
396c21dee17SSøren Schmidt 
397c9447c75SAlexander Leidinger int
398c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
399c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
400c9447c75SAlexander Leidinger {
401c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
4020f8dab45SDmitry Chagin 	struct l_timespec lts;
403db4a1f33SDmitry Chagin 	int error;
404c9447c75SAlexander Leidinger 
405c9447c75SAlexander Leidinger 	if (args->timeout) {
4060f8dab45SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
407c9447c75SAlexander Leidinger 			return (error);
4080f8dab45SDmitry Chagin 		error = linux_to_native_timespec(&ts, &lts);
4090f8dab45SDmitry Chagin 		if (error != 0)
4100f8dab45SDmitry Chagin 			return (error);
411c9447c75SAlexander Leidinger 		tsa = &ts;
4120f8dab45SDmitry Chagin 	} else
4130f8dab45SDmitry Chagin 		tsa = NULL;
4140f8dab45SDmitry Chagin 
415db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
416db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
417db4a1f33SDmitry Chagin }
418db4a1f33SDmitry Chagin 
419db4a1f33SDmitry Chagin static int
420db4a1f33SDmitry Chagin linux_common_rt_sigtimedwait(struct thread *td, l_sigset_t *mask,
421db4a1f33SDmitry Chagin     struct timespec *tsa, l_siginfo_t *ptr, l_size_t sigsetsize)
422db4a1f33SDmitry Chagin {
423db4a1f33SDmitry Chagin 	int error, sig;
424db4a1f33SDmitry Chagin 	l_sigset_t lset;
425db4a1f33SDmitry Chagin 	sigset_t bset;
426db4a1f33SDmitry Chagin 	l_siginfo_t lsi;
427db4a1f33SDmitry Chagin 	ksiginfo_t ksi;
428db4a1f33SDmitry Chagin 
429db4a1f33SDmitry Chagin 	if (sigsetsize != sizeof(l_sigset_t))
430db4a1f33SDmitry Chagin 		return (EINVAL);
431db4a1f33SDmitry Chagin 
432db4a1f33SDmitry Chagin 	if ((error = copyin(mask, &lset, sizeof(lset))))
433db4a1f33SDmitry Chagin 		return (error);
434db4a1f33SDmitry Chagin 	linux_to_bsd_sigset(&lset, &bset);
435db4a1f33SDmitry Chagin 
436db4a1f33SDmitry Chagin 	ksiginfo_init(&ksi);
437f4e80108SDmitry Chagin 	error = kern_sigtimedwait(td, bset, &ksi, tsa);
438c9447c75SAlexander Leidinger 	if (error)
439c9447c75SAlexander Leidinger 		return (error);
440c9447c75SAlexander Leidinger 
441f4e80108SDmitry Chagin 	sig = bsd_to_linux_signal(ksi.ksi_signo);
442f3481dd9SDmitry Chagin 
443db4a1f33SDmitry Chagin 	if (ptr) {
444f4e80108SDmitry Chagin 		memset(&lsi, 0, sizeof(lsi));
445f4e80108SDmitry Chagin 		siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
446db4a1f33SDmitry Chagin 		error = copyout(&lsi, ptr, sizeof(lsi));
447c9447c75SAlexander Leidinger 	}
448f3481dd9SDmitry Chagin 	if (error == 0)
449f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
450c9447c75SAlexander Leidinger 
451c9447c75SAlexander Leidinger 	return (error);
452c9447c75SAlexander Leidinger }
453c9447c75SAlexander Leidinger 
454db4a1f33SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
455db4a1f33SDmitry Chagin int
456db4a1f33SDmitry Chagin linux_rt_sigtimedwait_time64(struct thread *td,
457db4a1f33SDmitry Chagin 	struct linux_rt_sigtimedwait_time64_args *args)
458db4a1f33SDmitry Chagin {
459db4a1f33SDmitry Chagin 	struct timespec ts, *tsa;
460db4a1f33SDmitry Chagin 	struct l_timespec64 lts;
461db4a1f33SDmitry Chagin 	int error;
462db4a1f33SDmitry Chagin 
463db4a1f33SDmitry Chagin 	if (args->timeout) {
464db4a1f33SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
465db4a1f33SDmitry Chagin 			return (error);
466db4a1f33SDmitry Chagin 		error = linux_to_native_timespec64(&ts, &lts);
467db4a1f33SDmitry Chagin 		if (error != 0)
468db4a1f33SDmitry Chagin 			return (error);
469db4a1f33SDmitry Chagin 		tsa = &ts;
470db4a1f33SDmitry Chagin 	} else
471db4a1f33SDmitry Chagin 		tsa = NULL;
472db4a1f33SDmitry Chagin 
473db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
474db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
475db4a1f33SDmitry Chagin }
476db4a1f33SDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
477db4a1f33SDmitry Chagin 
478c21dee17SSøren Schmidt int
479b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
480c21dee17SSøren Schmidt {
48134ad5ac2SEdward Tomasz Napierala 	int l_signum;
482c21dee17SSøren Schmidt 
483956d3333SMarcel Moolenaar 	/*
484956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
485956d3333SMarcel Moolenaar 	 */
48664742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
4879a6a64d3SDmitry Chagin 		return (EINVAL);
488956d3333SMarcel Moolenaar 
4894ab7403bSDmitry Chagin 	if (args->signum > 0)
49034ad5ac2SEdward Tomasz Napierala 		l_signum = linux_to_bsd_signal(args->signum);
491956d3333SMarcel Moolenaar 	else
49234ad5ac2SEdward Tomasz Napierala 		l_signum = 0;
493956d3333SMarcel Moolenaar 
49434ad5ac2SEdward Tomasz Napierala 	return (kern_kill(td, args->pid, l_signum));
495c21dee17SSøren Schmidt }
4969b44bfc5SAlexander Leidinger 
497aa8b2011SKonstantin Belousov static int
49881338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
499aa8b2011SKonstantin Belousov {
500aa8b2011SKonstantin Belousov 	struct proc *p;
501aa8b2011SKonstantin Belousov 	int error;
502aa8b2011SKonstantin Belousov 
50381338031SDmitry Chagin 	p = tdt->td_proc;
50481338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
50581338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
50614961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
50781338031SDmitry Chagin 
50881338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
50981338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
510aa8b2011SKonstantin Belousov 		goto out;
511aa8b2011SKonstantin Belousov 
51281338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
513aa8b2011SKonstantin Belousov 
514aa8b2011SKonstantin Belousov out:
515aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
516aa8b2011SKonstantin Belousov 	return (error);
517aa8b2011SKonstantin Belousov }
518aa8b2011SKonstantin Belousov 
5199b44bfc5SAlexander Leidinger int
5209b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5219b44bfc5SAlexander Leidinger {
52281338031SDmitry Chagin 	struct thread *tdt;
52381338031SDmitry Chagin 	ksiginfo_t ksi;
52481338031SDmitry Chagin 	int sig;
5259b44bfc5SAlexander Leidinger 
526aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
527aa8b2011SKonstantin Belousov 		return (EINVAL);
5289b44bfc5SAlexander Leidinger 
52981338031SDmitry Chagin 	/*
53081338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
53181338031SDmitry Chagin 	 */
53281338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
53381338031SDmitry Chagin 		return (EINVAL);
53481338031SDmitry Chagin 
5354ab7403bSDmitry Chagin 	if (args->sig > 0)
5364ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
53781338031SDmitry Chagin 	else
5384ab7403bSDmitry Chagin 		sig = 0;
53981338031SDmitry Chagin 
54081338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
54181338031SDmitry Chagin 	if (tdt == NULL)
54281338031SDmitry Chagin 		return (ESRCH);
54381338031SDmitry Chagin 
54481338031SDmitry Chagin 	ksiginfo_init(&ksi);
54581338031SDmitry Chagin 	ksi.ksi_signo = sig;
546fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
54781338031SDmitry Chagin 	ksi.ksi_errno = 0;
54881338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
54981338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
55081338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
5519b44bfc5SAlexander Leidinger }
5529b44bfc5SAlexander Leidinger 
55381338031SDmitry Chagin /*
55481338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
55581338031SDmitry Chagin  */
5569b44bfc5SAlexander Leidinger int
5579b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5589b44bfc5SAlexander Leidinger {
55981338031SDmitry Chagin 	struct thread *tdt;
56081338031SDmitry Chagin 	ksiginfo_t ksi;
56181338031SDmitry Chagin 	int sig;
56281338031SDmitry Chagin 
563aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
564aa8b2011SKonstantin Belousov 		return (EINVAL);
5659b44bfc5SAlexander Leidinger 
56681338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
56781338031SDmitry Chagin 		return (EINVAL);
56881338031SDmitry Chagin 
5694ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
57081338031SDmitry Chagin 
57181338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
57281338031SDmitry Chagin 	if (tdt == NULL)
57381338031SDmitry Chagin 		return (ESRCH);
57481338031SDmitry Chagin 
57581338031SDmitry Chagin 	ksiginfo_init(&ksi);
57681338031SDmitry Chagin 	ksi.ksi_signo = sig;
577fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
57881338031SDmitry Chagin 	ksi.ksi_errno = 0;
57981338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
58081338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
58181338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
582aa8b2011SKonstantin Belousov }
583aa8b2011SKonstantin Belousov 
584fe4ed1e7SDmitry Chagin static void
585fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
586fe4ed1e7SDmitry Chagin {
587fe4ed1e7SDmitry Chagin 
588fe4ed1e7SDmitry Chagin 	switch (si_code) {
589fe4ed1e7SDmitry Chagin 	case SI_USER:
590fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
591fe4ed1e7SDmitry Chagin 		break;
592fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
593fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
594fe4ed1e7SDmitry Chagin 		break;
595fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
596fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
597fe4ed1e7SDmitry Chagin 		break;
598fe4ed1e7SDmitry Chagin 	case SI_TIMER:
599fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
600fe4ed1e7SDmitry Chagin 		break;
601fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
602fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
603fe4ed1e7SDmitry Chagin 		break;
604fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
605fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
606fe4ed1e7SDmitry Chagin 		break;
607fe4ed1e7SDmitry Chagin 	case SI_LWP:
608fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
609fe4ed1e7SDmitry Chagin 		break;
610fe4ed1e7SDmitry Chagin 	default:
611fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
612fe4ed1e7SDmitry Chagin 		break;
613fe4ed1e7SDmitry Chagin 	}
614fe4ed1e7SDmitry Chagin }
615fe4ed1e7SDmitry Chagin 
616fe4ed1e7SDmitry Chagin void
617fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
618fe4ed1e7SDmitry Chagin {
619fe4ed1e7SDmitry Chagin 
620fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
621fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
622fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
623fe4ed1e7SDmitry Chagin 
624fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
625fe4ed1e7SDmitry Chagin 	case SI_LWP:
626fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
627fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
628fe4ed1e7SDmitry Chagin 		break;
629fe4ed1e7SDmitry Chagin 
630fe4ed1e7SDmitry Chagin 	case SI_TIMER:
631fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
632fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
633fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
634fe4ed1e7SDmitry Chagin 		break;
635fe4ed1e7SDmitry Chagin 
636fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
637fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
638fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
639fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
640fe4ed1e7SDmitry Chagin 		break;
641fe4ed1e7SDmitry Chagin 
642fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
643fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
644fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
645fe4ed1e7SDmitry Chagin 		break;
646fe4ed1e7SDmitry Chagin 
647fe4ed1e7SDmitry Chagin 	default:
648aa8b2011SKonstantin Belousov 		switch (sig) {
649aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
650aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
651fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
652aa8b2011SKonstantin Belousov 			break;
653fe4ed1e7SDmitry Chagin 
654aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
655fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
656fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
657fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
658fe4ed1e7SDmitry Chagin 
659fe4ed1e7SDmitry Chagin 			if (si->si_code == CLD_STOPPED)
6604ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
661fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
6624ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
663fe4ed1e7SDmitry Chagin 			else
664fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
665aa8b2011SKonstantin Belousov 			break;
666fe4ed1e7SDmitry Chagin 
667aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
668aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
669aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
670aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
671fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
672aa8b2011SKonstantin Belousov 			break;
673fe4ed1e7SDmitry Chagin 
674aa8b2011SKonstantin Belousov 		default:
675fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
676fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
677fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
678fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
679fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
680fe4ed1e7SDmitry Chagin 			}
681aa8b2011SKonstantin Belousov 			break;
682aa8b2011SKonstantin Belousov 		}
683fe4ed1e7SDmitry Chagin 		break;
68409d6cb0aSDmitry Chagin 	}
6859b44bfc5SAlexander Leidinger }
6867ac9766dSDmitry Chagin 
6879c1045ffSDmitry Chagin int
6889c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
6899c1045ffSDmitry Chagin     siginfo_t *si, int sig)
6907ac9766dSDmitry Chagin {
6917ac9766dSDmitry Chagin 
6929c1045ffSDmitry Chagin 	switch (lsi->lsi_code) {
6939c1045ffSDmitry Chagin 	case LINUX_SI_TKILL:
6949c1045ffSDmitry Chagin 		if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
6959c1045ffSDmitry Chagin 			linux_msg(td, "SI_TKILL forbidden since 2.6.39");
6969c1045ffSDmitry Chagin 			return (EPERM);
6979c1045ffSDmitry Chagin 		}
6989c1045ffSDmitry Chagin 		si->si_code = SI_LWP;
6999c1045ffSDmitry Chagin 	case LINUX_SI_QUEUE:
7009c1045ffSDmitry Chagin 		si->si_code = SI_QUEUE;
7019c1045ffSDmitry Chagin 		break;
7029c1045ffSDmitry Chagin 	case LINUX_SI_TIMER:
7039c1045ffSDmitry Chagin 		si->si_code = SI_TIMER;
7049c1045ffSDmitry Chagin 		break;
7059c1045ffSDmitry Chagin 	case LINUX_SI_MESGQ:
7069c1045ffSDmitry Chagin 		si->si_code = SI_MESGQ;
7079c1045ffSDmitry Chagin 		break;
7089c1045ffSDmitry Chagin 	case LINUX_SI_ASYNCIO:
7099c1045ffSDmitry Chagin 		si->si_code = SI_ASYNCIO;
7109c1045ffSDmitry Chagin 		break;
7119c1045ffSDmitry Chagin 	default:
7129c1045ffSDmitry Chagin 		si->si_code = lsi->lsi_code;
7139c1045ffSDmitry Chagin 		break;
7149c1045ffSDmitry Chagin 	}
7159c1045ffSDmitry Chagin 
7169c1045ffSDmitry Chagin 	si->si_signo = sig;
7179c1045ffSDmitry Chagin 	si->si_pid = td->td_proc->p_pid;
7189c1045ffSDmitry Chagin 	si->si_uid = td->td_ucred->cr_ruid;
7199c1045ffSDmitry Chagin 	si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
7209c1045ffSDmitry Chagin 	return (0);
7217ac9766dSDmitry Chagin }
7227ac9766dSDmitry Chagin 
7237ac9766dSDmitry Chagin int
7247ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7257ac9766dSDmitry Chagin {
7267ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7277ac9766dSDmitry Chagin 	struct proc *p;
7287ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7297ac9766dSDmitry Chagin 	int error;
7307ac9766dSDmitry Chagin 	int sig;
7317ac9766dSDmitry Chagin 
7327ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7337ac9766dSDmitry Chagin 		return (EINVAL);
7347ac9766dSDmitry Chagin 
7357ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7367ac9766dSDmitry Chagin 	if (error != 0)
7377ac9766dSDmitry Chagin 		return (error);
7387ac9766dSDmitry Chagin 
7397ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7409c1045ffSDmitry Chagin 		/* SI_USER, SI_KERNEL */
7417ac9766dSDmitry Chagin 		return (EPERM);
7427ac9766dSDmitry Chagin 
7434ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7449c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7459c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7469c1045ffSDmitry Chagin 	if (error != 0)
7479c1045ffSDmitry Chagin 		return (error);
7487ac9766dSDmitry Chagin 
7497ac9766dSDmitry Chagin 	error = ESRCH;
750537d0fb1SMateusz Guzik 	if ((p = pfind_any(args->pid)) != NULL) {
7517ac9766dSDmitry Chagin 		error = p_cansignal(td, p, sig);
7527ac9766dSDmitry Chagin 		if (error != 0) {
7537ac9766dSDmitry Chagin 			PROC_UNLOCK(p);
7547ac9766dSDmitry Chagin 			return (error);
7557ac9766dSDmitry Chagin 		}
7567ac9766dSDmitry Chagin 		error = tdsendsignal(p, NULL, sig, &ksi);
7577ac9766dSDmitry Chagin 		PROC_UNLOCK(p);
7587ac9766dSDmitry Chagin 	}
7597ac9766dSDmitry Chagin 
7607ac9766dSDmitry Chagin 	return (error);
7617ac9766dSDmitry Chagin }
762486a06bdSDmitry Chagin 
763486a06bdSDmitry Chagin int
764486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
765486a06bdSDmitry Chagin {
766486a06bdSDmitry Chagin 	l_siginfo_t linfo;
767486a06bdSDmitry Chagin 	struct thread *tds;
768486a06bdSDmitry Chagin 	ksiginfo_t ksi;
769486a06bdSDmitry Chagin 	int error;
770486a06bdSDmitry Chagin 	int sig;
771486a06bdSDmitry Chagin 
772486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
773486a06bdSDmitry Chagin 		return (EINVAL);
774486a06bdSDmitry Chagin 
775486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
776486a06bdSDmitry Chagin 	if (error != 0)
777486a06bdSDmitry Chagin 		return (error);
778486a06bdSDmitry Chagin 
779486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
780486a06bdSDmitry Chagin 		return (EPERM);
781486a06bdSDmitry Chagin 
7829c1045ffSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7839c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7849c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7859c1045ffSDmitry Chagin 	if (error != 0)
7869c1045ffSDmitry Chagin 		return (error);
7879c1045ffSDmitry Chagin 
788486a06bdSDmitry Chagin 	tds = linux_tdfind(td, args->tid, args->tgid);
789486a06bdSDmitry Chagin 	if (tds == NULL)
790486a06bdSDmitry Chagin 		return (ESRCH);
791486a06bdSDmitry Chagin 
792486a06bdSDmitry Chagin 	return (linux_do_tkill(td, tds, &ksi));
793486a06bdSDmitry Chagin }
794