xref: /freebsd/sys/compat/linux/linux_signal.c (revision f4e801085b055fd33f680dd7cb9f8562d236f39a)
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);
63fe4ed1e7SDmitry Chagin 
64a1ebcbfbSPeter Wemm static void
655002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
66d66a5066SPeter Wemm {
67d5629eb2SEdward Tomasz Napierala 	unsigned long flags;
68956d3333SMarcel Moolenaar 
69956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
704af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
71d66a5066SPeter Wemm 	bsa->sa_flags = 0;
72d5629eb2SEdward Tomasz Napierala 
73d5629eb2SEdward Tomasz Napierala 	flags = lsa->lsa_flags;
74d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
75d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDSTOP;
76d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
77d5629eb2SEdward Tomasz Napierala 	}
78d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
79d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDWAIT;
8006ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
81d5629eb2SEdward Tomasz Napierala 	}
82d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
83d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_SIGINFO;
8406ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
85d5629eb2SEdward Tomasz Napierala #ifdef notyet
86d5629eb2SEdward Tomasz Napierala 		/*
87d5629eb2SEdward Tomasz Napierala 		 * XXX: We seem to be missing code to convert
88d5629eb2SEdward Tomasz Napierala 		 *      some of the fields in ucontext_t.
89d5629eb2SEdward Tomasz Napierala 		 */
90d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread,
91d5629eb2SEdward Tomasz Napierala 		    "partially unsupported sigaction flag SA_SIGINFO");
92d5629eb2SEdward Tomasz Napierala #endif
93d5629eb2SEdward Tomasz Napierala 	}
94d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTORER) {
95d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTORER;
96d5629eb2SEdward Tomasz Napierala 		/* XXX: We might want to handle it; see Linux sigreturn(2). */
97d5629eb2SEdward Tomasz Napierala 	}
98d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
99d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONSTACK;
100d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
101d5629eb2SEdward Tomasz Napierala 	}
102d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
103d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTART;
104d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
105d5629eb2SEdward Tomasz Napierala 	}
1069bc42c18SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
1079bc42c18SEdward Tomasz Napierala 		flags &= ~LINUX_SA_INTERRUPT;
1089bc42c18SEdward Tomasz Napierala 		/* Documented to be a "historical no-op". */
1099bc42c18SEdward Tomasz Napierala 	}
110d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
111d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONESHOT;
112d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
113d5629eb2SEdward Tomasz Napierala 	}
114d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
115d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOMASK;
116d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
117d66a5066SPeter Wemm 	}
118d66a5066SPeter Wemm 
119d5629eb2SEdward Tomasz Napierala 	if (flags != 0)
120d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
121d5629eb2SEdward Tomasz Napierala }
122d5629eb2SEdward Tomasz Napierala 
123a1ebcbfbSPeter Wemm static void
1245002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
125d66a5066SPeter Wemm {
126956d3333SMarcel Moolenaar 
127956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1281997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1294af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1304af27623STim J. Robbins #else
1318f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1324af27623STim J. Robbins #endif
1334af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1348f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
135d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1368f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
13706ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
13806ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
13906ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
14006ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
141d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1428f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
143d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1448f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
145d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1468f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
147d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1488f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
149d66a5066SPeter Wemm }
150c21dee17SSøren Schmidt 
151ba9ef45bSMarcel Moolenaar int
152b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1535002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
15406ebbe77SMarcel Moolenaar {
155206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
156206a5d3aSIan Dowse 	int error, sig;
15706ebbe77SMarcel Moolenaar 
158687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
159956d3333SMarcel Moolenaar 		return (EINVAL);
16006ebbe77SMarcel Moolenaar 
161206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
162956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
163206a5d3aSIan Dowse 		nsa = &act;
164ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
165206a5d3aSIan Dowse 	} else
16606ebbe77SMarcel Moolenaar 		nsa = NULL;
1674ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(linux_sig);
168956d3333SMarcel Moolenaar 
169206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
17006ebbe77SMarcel Moolenaar 	if (error)
171956d3333SMarcel Moolenaar 		return (error);
17206ebbe77SMarcel Moolenaar 
173ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
174ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
17506ebbe77SMarcel Moolenaar 
176956d3333SMarcel Moolenaar 	return (0);
17706ebbe77SMarcel Moolenaar }
17806ebbe77SMarcel Moolenaar 
1797f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
180c21dee17SSøren Schmidt int
181b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
182d66a5066SPeter Wemm {
1835002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
184d66a5066SPeter Wemm 	int error;
185d66a5066SPeter Wemm 
18606ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
18706ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
188956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
189d66a5066SPeter Wemm 
190b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1914af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
192d66a5066SPeter Wemm 
193956d3333SMarcel Moolenaar 	return (error);
194d66a5066SPeter Wemm }
1957f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
196d66a5066SPeter Wemm 
197c21dee17SSøren Schmidt int
198b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
199c21dee17SSøren Schmidt {
2005002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
20106ebbe77SMarcel Moolenaar 	int error;
202c21dee17SSøren Schmidt 
2035002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
204956d3333SMarcel Moolenaar 		return (EINVAL);
20506ebbe77SMarcel Moolenaar 
206956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2075002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
20806ebbe77SMarcel Moolenaar 		if (error)
209956d3333SMarcel Moolenaar 			return (error);
21006ebbe77SMarcel Moolenaar 	}
21106ebbe77SMarcel Moolenaar 
212b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
21306ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
21406ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
21506ebbe77SMarcel Moolenaar 
216956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2175002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
21806ebbe77SMarcel Moolenaar 	}
21906ebbe77SMarcel Moolenaar 
220956d3333SMarcel Moolenaar 	return (error);
22106ebbe77SMarcel Moolenaar }
22206ebbe77SMarcel Moolenaar 
22306ebbe77SMarcel Moolenaar static int
224b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2255002a60fSMarcel Moolenaar 		     l_sigset_t *old)
22606ebbe77SMarcel Moolenaar {
227fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
228fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
229216af822SJohn Baldwin 	int error;
23006ebbe77SMarcel Moolenaar 
231b40ce416SJulian Elischer 	td->td_retval[0] = 0;
232d66a5066SPeter Wemm 
23319dde5cdSJohn Baldwin 	switch (how) {
23419dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
23519dde5cdSJohn Baldwin 		how = SIG_BLOCK;
23619dde5cdSJohn Baldwin 		break;
23719dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
23819dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
23919dde5cdSJohn Baldwin 		break;
24019dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
24119dde5cdSJohn Baldwin 		how = SIG_SETMASK;
24219dde5cdSJohn Baldwin 		break;
24319dde5cdSJohn Baldwin 	default:
24419dde5cdSJohn Baldwin 		return (EINVAL);
24519dde5cdSJohn Baldwin 	}
24606ebbe77SMarcel Moolenaar 	if (new != NULL) {
247fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
248fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
249fe8cdcaeSJohn Baldwin 	} else
250fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
25119dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2522f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
253fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
25406ebbe77SMarcel Moolenaar 
255956d3333SMarcel Moolenaar 	return (error);
25606ebbe77SMarcel Moolenaar }
25706ebbe77SMarcel Moolenaar 
2587f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
25906ebbe77SMarcel Moolenaar int
260b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
26106ebbe77SMarcel Moolenaar {
2625002a60fSMarcel Moolenaar 	l_osigset_t mask;
2635002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
26406ebbe77SMarcel Moolenaar 	int error;
26506ebbe77SMarcel Moolenaar 
26606ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2675002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
26806ebbe77SMarcel Moolenaar 		if (error)
269956d3333SMarcel Moolenaar 			return (error);
270956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
2714ab7403bSDmitry Chagin 		set.__mask = mask;
27206ebbe77SMarcel Moolenaar 	}
27306ebbe77SMarcel Moolenaar 
274b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
275956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
276956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
27706ebbe77SMarcel Moolenaar 
278956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
2794ab7403bSDmitry Chagin 		mask = oset.__mask;
2805002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
28106ebbe77SMarcel Moolenaar 	}
28206ebbe77SMarcel Moolenaar 
283956d3333SMarcel Moolenaar 	return (error);
28406ebbe77SMarcel Moolenaar }
2857f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
28606ebbe77SMarcel Moolenaar 
28706ebbe77SMarcel Moolenaar int
288b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
28906ebbe77SMarcel Moolenaar {
2905002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
29106ebbe77SMarcel Moolenaar 	int error;
29206ebbe77SMarcel Moolenaar 
2935002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
294340f4a8dSEd Maste 		return (EINVAL);
29506ebbe77SMarcel Moolenaar 
29606ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2975002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
29806ebbe77SMarcel Moolenaar 		if (error)
299956d3333SMarcel Moolenaar 			return (error);
30006ebbe77SMarcel Moolenaar 	}
30106ebbe77SMarcel Moolenaar 
302b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
303956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
304956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
30506ebbe77SMarcel Moolenaar 
306956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3075002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
30806ebbe77SMarcel Moolenaar 	}
30906ebbe77SMarcel Moolenaar 
310956d3333SMarcel Moolenaar 	return (error);
311c21dee17SSøren Schmidt }
312c21dee17SSøren Schmidt 
3137f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
314c21dee17SSøren Schmidt int
315b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
316c21dee17SSøren Schmidt {
317b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3185002a60fSMarcel Moolenaar 	l_sigset_t mask;
319956d3333SMarcel Moolenaar 
320216af822SJohn Baldwin 	PROC_LOCK(p);
3214093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
322216af822SJohn Baldwin 	PROC_UNLOCK(p);
3234ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
324956d3333SMarcel Moolenaar 	return (0);
325c21dee17SSøren Schmidt }
326c21dee17SSøren Schmidt 
327c21dee17SSøren Schmidt int
328b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
329c21dee17SSøren Schmidt {
330b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3315002a60fSMarcel Moolenaar 	l_sigset_t lset;
332956d3333SMarcel Moolenaar 	sigset_t bset;
333c21dee17SSøren Schmidt 
334216af822SJohn Baldwin 	PROC_LOCK(p);
3354093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3364ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
337956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3384ab7403bSDmitry Chagin 	lset.__mask = args->mask;
339956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3404093529dSJeff Roberson 	td->td_sigmask = bset;
3414093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3424093529dSJeff Roberson 	signotify(td);
343216af822SJohn Baldwin 	PROC_UNLOCK(p);
344956d3333SMarcel Moolenaar 	return (0);
345c21dee17SSøren Schmidt }
346c21dee17SSøren Schmidt 
347c21dee17SSøren Schmidt int
348b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
349c21dee17SSøren Schmidt {
350b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
351956d3333SMarcel Moolenaar 	sigset_t bset;
3525002a60fSMarcel Moolenaar 	l_sigset_t lset;
3535002a60fSMarcel Moolenaar 	l_osigset_t mask;
354c21dee17SSøren Schmidt 
355216af822SJohn Baldwin 	PROC_LOCK(p);
3561d9c5696SJuli Mallett 	bset = p->p_siglist;
3574093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3584093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
359216af822SJohn Baldwin 	PROC_UNLOCK(p);
3609d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
3614ab7403bSDmitry Chagin 	mask = lset.__mask;
362956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
363c21dee17SSøren Schmidt }
3647f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
36517138b61SAlexander Leidinger 
36617138b61SAlexander Leidinger /*
36717138b61SAlexander Leidinger  * MPSAFE
36817138b61SAlexander Leidinger  */
36917138b61SAlexander Leidinger int
37017138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
37117138b61SAlexander Leidinger {
37217138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
37317138b61SAlexander Leidinger 	sigset_t bset;
37417138b61SAlexander Leidinger 	l_sigset_t lset;
37517138b61SAlexander Leidinger 
37617138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
377340f4a8dSEd Maste 		return (EINVAL);
37817138b61SAlexander Leidinger 		/* NOT REACHED */
37917138b61SAlexander Leidinger 
38017138b61SAlexander Leidinger 	PROC_LOCK(p);
38117138b61SAlexander Leidinger 	bset = p->p_siglist;
38217138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
38317138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
38417138b61SAlexander Leidinger 	PROC_UNLOCK(p);
38517138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
38617138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
38717138b61SAlexander Leidinger }
388c21dee17SSøren Schmidt 
389c9447c75SAlexander Leidinger /*
390c9447c75SAlexander Leidinger  * MPSAFE
391c9447c75SAlexander Leidinger  */
392c9447c75SAlexander Leidinger int
393c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
394c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
395c9447c75SAlexander Leidinger {
396f3481dd9SDmitry Chagin 	int error, sig;
397c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
3980f8dab45SDmitry Chagin 	struct l_timespec lts;
399c9447c75SAlexander Leidinger 	l_sigset_t lset;
400c9447c75SAlexander Leidinger 	sigset_t bset;
401*f4e80108SDmitry Chagin 	l_siginfo_t lsi;
402*f4e80108SDmitry Chagin 	ksiginfo_t ksi;
403c9447c75SAlexander Leidinger 
404c9447c75SAlexander Leidinger 	if (args->sigsetsize != sizeof(l_sigset_t))
405c9447c75SAlexander Leidinger 		return (EINVAL);
406c9447c75SAlexander Leidinger 
407c9447c75SAlexander Leidinger 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
408c9447c75SAlexander Leidinger 		return (error);
409c9447c75SAlexander Leidinger 	linux_to_bsd_sigset(&lset, &bset);
410c9447c75SAlexander Leidinger 
411c9447c75SAlexander Leidinger 	tsa = NULL;
412c9447c75SAlexander Leidinger 	if (args->timeout) {
4130f8dab45SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
414c9447c75SAlexander Leidinger 			return (error);
4150f8dab45SDmitry Chagin 		error = linux_to_native_timespec(&ts, &lts);
4160f8dab45SDmitry Chagin 		if (error != 0)
4170f8dab45SDmitry Chagin 			return (error);
418c9447c75SAlexander Leidinger 		tsa = &ts;
4190f8dab45SDmitry Chagin 	} else
4200f8dab45SDmitry Chagin 		tsa = NULL;
4210f8dab45SDmitry Chagin 
422*f4e80108SDmitry Chagin 	error = kern_sigtimedwait(td, bset, &ksi, tsa);
423c9447c75SAlexander Leidinger 	if (error)
424c9447c75SAlexander Leidinger 		return (error);
425c9447c75SAlexander Leidinger 
426*f4e80108SDmitry Chagin 	sig = bsd_to_linux_signal(ksi.ksi_signo);
427f3481dd9SDmitry Chagin 
428c9447c75SAlexander Leidinger 	if (args->ptr) {
429*f4e80108SDmitry Chagin 		memset(&lsi, 0, sizeof(lsi));
430*f4e80108SDmitry Chagin 		siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
431*f4e80108SDmitry Chagin 		error = copyout(&lsi, args->ptr, sizeof(lsi));
432c9447c75SAlexander Leidinger 	}
433f3481dd9SDmitry Chagin 	if (error == 0)
434f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
435c9447c75SAlexander Leidinger 
436c9447c75SAlexander Leidinger 	return (error);
437c9447c75SAlexander Leidinger }
438c9447c75SAlexander Leidinger 
439c21dee17SSøren Schmidt int
440b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
441c21dee17SSøren Schmidt {
44234ad5ac2SEdward Tomasz Napierala 	int l_signum;
443c21dee17SSøren Schmidt 
444956d3333SMarcel Moolenaar 	/*
445956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
446956d3333SMarcel Moolenaar 	 */
44764742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
4489a6a64d3SDmitry Chagin 		return (EINVAL);
449956d3333SMarcel Moolenaar 
4504ab7403bSDmitry Chagin 	if (args->signum > 0)
45134ad5ac2SEdward Tomasz Napierala 		l_signum = linux_to_bsd_signal(args->signum);
452956d3333SMarcel Moolenaar 	else
45334ad5ac2SEdward Tomasz Napierala 		l_signum = 0;
454956d3333SMarcel Moolenaar 
45534ad5ac2SEdward Tomasz Napierala 	return (kern_kill(td, args->pid, l_signum));
456c21dee17SSøren Schmidt }
4579b44bfc5SAlexander Leidinger 
458aa8b2011SKonstantin Belousov static int
45981338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
460aa8b2011SKonstantin Belousov {
461aa8b2011SKonstantin Belousov 	struct proc *p;
462aa8b2011SKonstantin Belousov 	int error;
463aa8b2011SKonstantin Belousov 
46481338031SDmitry Chagin 	p = tdt->td_proc;
46581338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
46681338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
46714961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
46881338031SDmitry Chagin 
46981338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
47081338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
471aa8b2011SKonstantin Belousov 		goto out;
472aa8b2011SKonstantin Belousov 
47381338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
474aa8b2011SKonstantin Belousov 
475aa8b2011SKonstantin Belousov out:
476aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
477aa8b2011SKonstantin Belousov 	return (error);
478aa8b2011SKonstantin Belousov }
479aa8b2011SKonstantin Belousov 
4809b44bfc5SAlexander Leidinger int
4819b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
4829b44bfc5SAlexander Leidinger {
48381338031SDmitry Chagin 	struct thread *tdt;
48481338031SDmitry Chagin 	ksiginfo_t ksi;
48581338031SDmitry Chagin 	int sig;
4869b44bfc5SAlexander Leidinger 
487aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
488aa8b2011SKonstantin Belousov 		return (EINVAL);
4899b44bfc5SAlexander Leidinger 
49081338031SDmitry Chagin 	/*
49181338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
49281338031SDmitry Chagin 	 */
49381338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
49481338031SDmitry Chagin 		return (EINVAL);
49581338031SDmitry Chagin 
4964ab7403bSDmitry Chagin 	if (args->sig > 0)
4974ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
49881338031SDmitry Chagin 	else
4994ab7403bSDmitry Chagin 		sig = 0;
50081338031SDmitry Chagin 
50181338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
50281338031SDmitry Chagin 	if (tdt == NULL)
50381338031SDmitry Chagin 		return (ESRCH);
50481338031SDmitry Chagin 
50581338031SDmitry Chagin 	ksiginfo_init(&ksi);
50681338031SDmitry Chagin 	ksi.ksi_signo = sig;
507fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
50881338031SDmitry Chagin 	ksi.ksi_errno = 0;
50981338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
51081338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
51181338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
5129b44bfc5SAlexander Leidinger }
5139b44bfc5SAlexander Leidinger 
51481338031SDmitry Chagin /*
51581338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
51681338031SDmitry Chagin  */
5179b44bfc5SAlexander Leidinger int
5189b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5199b44bfc5SAlexander Leidinger {
52081338031SDmitry Chagin 	struct thread *tdt;
52181338031SDmitry Chagin 	ksiginfo_t ksi;
52281338031SDmitry Chagin 	int sig;
52381338031SDmitry Chagin 
524aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
525aa8b2011SKonstantin Belousov 		return (EINVAL);
5269b44bfc5SAlexander Leidinger 
52781338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
52881338031SDmitry Chagin 		return (EINVAL);
52981338031SDmitry Chagin 
5304ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
53181338031SDmitry Chagin 
53281338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
53381338031SDmitry Chagin 	if (tdt == NULL)
53481338031SDmitry Chagin 		return (ESRCH);
53581338031SDmitry Chagin 
53681338031SDmitry Chagin 	ksiginfo_init(&ksi);
53781338031SDmitry Chagin 	ksi.ksi_signo = sig;
538fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
53981338031SDmitry Chagin 	ksi.ksi_errno = 0;
54081338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
54181338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
54281338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
543aa8b2011SKonstantin Belousov }
544aa8b2011SKonstantin Belousov 
545fe4ed1e7SDmitry Chagin static void
546fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
547fe4ed1e7SDmitry Chagin {
548fe4ed1e7SDmitry Chagin 
549fe4ed1e7SDmitry Chagin 	switch (si_code) {
550fe4ed1e7SDmitry Chagin 	case SI_USER:
551fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
552fe4ed1e7SDmitry Chagin 		break;
553fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
554fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
555fe4ed1e7SDmitry Chagin 		break;
556fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
557fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
558fe4ed1e7SDmitry Chagin 		break;
559fe4ed1e7SDmitry Chagin 	case SI_TIMER:
560fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
561fe4ed1e7SDmitry Chagin 		break;
562fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
563fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
564fe4ed1e7SDmitry Chagin 		break;
565fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
566fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
567fe4ed1e7SDmitry Chagin 		break;
568fe4ed1e7SDmitry Chagin 	case SI_LWP:
569fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
570fe4ed1e7SDmitry Chagin 		break;
571fe4ed1e7SDmitry Chagin 	default:
572fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
573fe4ed1e7SDmitry Chagin 		break;
574fe4ed1e7SDmitry Chagin 	}
575fe4ed1e7SDmitry Chagin }
576fe4ed1e7SDmitry Chagin 
577fe4ed1e7SDmitry Chagin void
578fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
579fe4ed1e7SDmitry Chagin {
580fe4ed1e7SDmitry Chagin 
581fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
582fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
583fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
584fe4ed1e7SDmitry Chagin 
585fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
586fe4ed1e7SDmitry Chagin 	case SI_LWP:
587fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
588fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
589fe4ed1e7SDmitry Chagin 		break;
590fe4ed1e7SDmitry Chagin 
591fe4ed1e7SDmitry Chagin 	case SI_TIMER:
592fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
593fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
594fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
595fe4ed1e7SDmitry Chagin 		break;
596fe4ed1e7SDmitry Chagin 
597fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
598fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
599fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
600fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
601fe4ed1e7SDmitry Chagin 		break;
602fe4ed1e7SDmitry Chagin 
603fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
604fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
605fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
606fe4ed1e7SDmitry Chagin 		break;
607fe4ed1e7SDmitry Chagin 
608fe4ed1e7SDmitry Chagin 	default:
609aa8b2011SKonstantin Belousov 		switch (sig) {
610aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
611aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
612fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
613aa8b2011SKonstantin Belousov 			break;
614fe4ed1e7SDmitry Chagin 
615aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
616fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
617fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
618fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
619fe4ed1e7SDmitry Chagin 
620fe4ed1e7SDmitry Chagin 			if (si->si_code == CLD_STOPPED)
6214ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
622fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
6234ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
624fe4ed1e7SDmitry Chagin 			else
625fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
626aa8b2011SKonstantin Belousov 			break;
627fe4ed1e7SDmitry Chagin 
628aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
629aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
630aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
631aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
632fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
633aa8b2011SKonstantin Belousov 			break;
634fe4ed1e7SDmitry Chagin 
635aa8b2011SKonstantin Belousov 		default:
636fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
637fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
638fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
639fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
640fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
641fe4ed1e7SDmitry Chagin 			}
642aa8b2011SKonstantin Belousov 			break;
643aa8b2011SKonstantin Belousov 		}
644fe4ed1e7SDmitry Chagin 		break;
64509d6cb0aSDmitry Chagin 	}
6469b44bfc5SAlexander Leidinger }
6477ac9766dSDmitry Chagin 
6489c1045ffSDmitry Chagin int
6499c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
6509c1045ffSDmitry Chagin     siginfo_t *si, int sig)
6517ac9766dSDmitry Chagin {
6527ac9766dSDmitry Chagin 
6539c1045ffSDmitry Chagin 	switch (lsi->lsi_code) {
6549c1045ffSDmitry Chagin 	case LINUX_SI_TKILL:
6559c1045ffSDmitry Chagin 		if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
6569c1045ffSDmitry Chagin 			linux_msg(td, "SI_TKILL forbidden since 2.6.39");
6579c1045ffSDmitry Chagin 			return (EPERM);
6589c1045ffSDmitry Chagin 		}
6599c1045ffSDmitry Chagin 		si->si_code = SI_LWP;
6609c1045ffSDmitry Chagin 	case LINUX_SI_QUEUE:
6619c1045ffSDmitry Chagin 		si->si_code = SI_QUEUE;
6629c1045ffSDmitry Chagin 		break;
6639c1045ffSDmitry Chagin 	case LINUX_SI_TIMER:
6649c1045ffSDmitry Chagin 		si->si_code = SI_TIMER;
6659c1045ffSDmitry Chagin 		break;
6669c1045ffSDmitry Chagin 	case LINUX_SI_MESGQ:
6679c1045ffSDmitry Chagin 		si->si_code = SI_MESGQ;
6689c1045ffSDmitry Chagin 		break;
6699c1045ffSDmitry Chagin 	case LINUX_SI_ASYNCIO:
6709c1045ffSDmitry Chagin 		si->si_code = SI_ASYNCIO;
6719c1045ffSDmitry Chagin 		break;
6729c1045ffSDmitry Chagin 	default:
6739c1045ffSDmitry Chagin 		si->si_code = lsi->lsi_code;
6749c1045ffSDmitry Chagin 		break;
6759c1045ffSDmitry Chagin 	}
6769c1045ffSDmitry Chagin 
6779c1045ffSDmitry Chagin 	si->si_signo = sig;
6789c1045ffSDmitry Chagin 	si->si_pid = td->td_proc->p_pid;
6799c1045ffSDmitry Chagin 	si->si_uid = td->td_ucred->cr_ruid;
6809c1045ffSDmitry Chagin 	si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
6819c1045ffSDmitry Chagin 	return (0);
6827ac9766dSDmitry Chagin }
6837ac9766dSDmitry Chagin 
6847ac9766dSDmitry Chagin int
6857ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
6867ac9766dSDmitry Chagin {
6877ac9766dSDmitry Chagin 	l_siginfo_t linfo;
6887ac9766dSDmitry Chagin 	struct proc *p;
6897ac9766dSDmitry Chagin 	ksiginfo_t ksi;
6907ac9766dSDmitry Chagin 	int error;
6917ac9766dSDmitry Chagin 	int sig;
6927ac9766dSDmitry Chagin 
6937ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
6947ac9766dSDmitry Chagin 		return (EINVAL);
6957ac9766dSDmitry Chagin 
6967ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
6977ac9766dSDmitry Chagin 	if (error != 0)
6987ac9766dSDmitry Chagin 		return (error);
6997ac9766dSDmitry Chagin 
7007ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7019c1045ffSDmitry Chagin 		/* SI_USER, SI_KERNEL */
7027ac9766dSDmitry Chagin 		return (EPERM);
7037ac9766dSDmitry Chagin 
7044ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7059c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7069c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7079c1045ffSDmitry Chagin 	if (error != 0)
7089c1045ffSDmitry Chagin 		return (error);
7097ac9766dSDmitry Chagin 
7107ac9766dSDmitry Chagin 	error = ESRCH;
711537d0fb1SMateusz Guzik 	if ((p = pfind_any(args->pid)) != NULL) {
7127ac9766dSDmitry Chagin 		error = p_cansignal(td, p, sig);
7137ac9766dSDmitry Chagin 		if (error != 0) {
7147ac9766dSDmitry Chagin 			PROC_UNLOCK(p);
7157ac9766dSDmitry Chagin 			return (error);
7167ac9766dSDmitry Chagin 		}
7177ac9766dSDmitry Chagin 		error = tdsendsignal(p, NULL, sig, &ksi);
7187ac9766dSDmitry Chagin 		PROC_UNLOCK(p);
7197ac9766dSDmitry Chagin 	}
7207ac9766dSDmitry Chagin 
7217ac9766dSDmitry Chagin 	return (error);
7227ac9766dSDmitry Chagin }
723486a06bdSDmitry Chagin 
724486a06bdSDmitry Chagin int
725486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
726486a06bdSDmitry Chagin {
727486a06bdSDmitry Chagin 	l_siginfo_t linfo;
728486a06bdSDmitry Chagin 	struct thread *tds;
729486a06bdSDmitry Chagin 	ksiginfo_t ksi;
730486a06bdSDmitry Chagin 	int error;
731486a06bdSDmitry Chagin 	int sig;
732486a06bdSDmitry Chagin 
733486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
734486a06bdSDmitry Chagin 		return (EINVAL);
735486a06bdSDmitry Chagin 
736486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
737486a06bdSDmitry Chagin 	if (error != 0)
738486a06bdSDmitry Chagin 		return (error);
739486a06bdSDmitry Chagin 
740486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
741486a06bdSDmitry Chagin 		return (EPERM);
742486a06bdSDmitry Chagin 
7439c1045ffSDmitry 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);
7489c1045ffSDmitry Chagin 
749486a06bdSDmitry Chagin 	tds = linux_tdfind(td, args->tid, args->tgid);
750486a06bdSDmitry Chagin 	if (tds == NULL)
751486a06bdSDmitry Chagin 		return (ESRCH);
752486a06bdSDmitry Chagin 
753486a06bdSDmitry Chagin 	return (linux_do_tkill(td, tds, &ksi));
754486a06bdSDmitry Chagin }
755