xref: /freebsd/sys/compat/linux/linux_signal.c (revision db4a1f331b73eb821d5d9c3cbb478ad50223f023)
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);
63*db4a1f33SDmitry Chagin static int	linux_common_rt_sigtimedwait(struct thread *,
64*db4a1f33SDmitry Chagin 		    l_sigset_t *, struct timespec *, l_siginfo_t *,
65*db4a1f33SDmitry 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;
99d5629eb2SEdward Tomasz Napierala 		/* XXX: We might want to handle it; see Linux sigreturn(2). */
100d5629eb2SEdward Tomasz Napierala 	}
101d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
102d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONSTACK;
103d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
104d5629eb2SEdward Tomasz Napierala 	}
105d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
106d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTART;
107d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
108d5629eb2SEdward Tomasz Napierala 	}
1099bc42c18SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
1109bc42c18SEdward Tomasz Napierala 		flags &= ~LINUX_SA_INTERRUPT;
1119bc42c18SEdward Tomasz Napierala 		/* Documented to be a "historical no-op". */
1129bc42c18SEdward Tomasz Napierala 	}
113d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
114d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONESHOT;
115d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
116d5629eb2SEdward Tomasz Napierala 	}
117d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
118d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOMASK;
119d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
120d66a5066SPeter Wemm 	}
121d66a5066SPeter Wemm 
122d5629eb2SEdward Tomasz Napierala 	if (flags != 0)
123d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
124d5629eb2SEdward Tomasz Napierala }
125d5629eb2SEdward Tomasz Napierala 
126a1ebcbfbSPeter Wemm static void
1275002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
128d66a5066SPeter Wemm {
129956d3333SMarcel Moolenaar 
130956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1311997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1324af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1334af27623STim J. Robbins #else
1348f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1354af27623STim J. Robbins #endif
1364af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1378f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
138d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1398f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
14006ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
14106ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
14206ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
14306ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
144d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1458f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
146d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1478f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
148d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1498f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
150d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1518f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
152d66a5066SPeter Wemm }
153c21dee17SSøren Schmidt 
154ba9ef45bSMarcel Moolenaar int
155b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1565002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
15706ebbe77SMarcel Moolenaar {
158206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
159206a5d3aSIan Dowse 	int error, sig;
16006ebbe77SMarcel Moolenaar 
161687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
162956d3333SMarcel Moolenaar 		return (EINVAL);
16306ebbe77SMarcel Moolenaar 
164206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
165956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
166206a5d3aSIan Dowse 		nsa = &act;
167ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
168206a5d3aSIan Dowse 	} else
16906ebbe77SMarcel Moolenaar 		nsa = NULL;
1704ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(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 
1827f8f1d7fSDmitry 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 
18906ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
19006ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
191956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
192d66a5066SPeter Wemm 
193b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1944af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
195d66a5066SPeter Wemm 
196956d3333SMarcel Moolenaar 	return (error);
197d66a5066SPeter Wemm }
1987f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
199d66a5066SPeter Wemm 
200c21dee17SSøren Schmidt int
201b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
202c21dee17SSøren Schmidt {
2035002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
20406ebbe77SMarcel Moolenaar 	int error;
205c21dee17SSøren Schmidt 
2065002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
207956d3333SMarcel Moolenaar 		return (EINVAL);
20806ebbe77SMarcel Moolenaar 
209956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2105002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21106ebbe77SMarcel Moolenaar 		if (error)
212956d3333SMarcel Moolenaar 			return (error);
21306ebbe77SMarcel Moolenaar 	}
21406ebbe77SMarcel Moolenaar 
215b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
21606ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
21706ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
21806ebbe77SMarcel Moolenaar 
219956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2205002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22106ebbe77SMarcel Moolenaar 	}
22206ebbe77SMarcel Moolenaar 
223956d3333SMarcel Moolenaar 	return (error);
22406ebbe77SMarcel Moolenaar }
22506ebbe77SMarcel Moolenaar 
22606ebbe77SMarcel Moolenaar static int
227b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2285002a60fSMarcel Moolenaar 		     l_sigset_t *old)
22906ebbe77SMarcel Moolenaar {
230fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
231fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
232216af822SJohn Baldwin 	int error;
23306ebbe77SMarcel Moolenaar 
234b40ce416SJulian Elischer 	td->td_retval[0] = 0;
235d66a5066SPeter Wemm 
23619dde5cdSJohn Baldwin 	switch (how) {
23719dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
23819dde5cdSJohn Baldwin 		how = SIG_BLOCK;
23919dde5cdSJohn Baldwin 		break;
24019dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
24119dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
24219dde5cdSJohn Baldwin 		break;
24319dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
24419dde5cdSJohn Baldwin 		how = SIG_SETMASK;
24519dde5cdSJohn Baldwin 		break;
24619dde5cdSJohn Baldwin 	default:
24719dde5cdSJohn Baldwin 		return (EINVAL);
24819dde5cdSJohn Baldwin 	}
24906ebbe77SMarcel Moolenaar 	if (new != NULL) {
250fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
251fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
252fe8cdcaeSJohn Baldwin 	} else
253fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
25419dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2552f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
256fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
25706ebbe77SMarcel Moolenaar 
258956d3333SMarcel Moolenaar 	return (error);
25906ebbe77SMarcel Moolenaar }
26006ebbe77SMarcel Moolenaar 
2617f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
26206ebbe77SMarcel Moolenaar int
263b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
26406ebbe77SMarcel Moolenaar {
2655002a60fSMarcel Moolenaar 	l_osigset_t mask;
2665002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
26706ebbe77SMarcel Moolenaar 	int error;
26806ebbe77SMarcel Moolenaar 
26906ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2705002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
27106ebbe77SMarcel Moolenaar 		if (error)
272956d3333SMarcel Moolenaar 			return (error);
273956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
2744ab7403bSDmitry Chagin 		set.__mask = mask;
27506ebbe77SMarcel Moolenaar 	}
27606ebbe77SMarcel Moolenaar 
277b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
278956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
279956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
28006ebbe77SMarcel Moolenaar 
281956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
2824ab7403bSDmitry Chagin 		mask = oset.__mask;
2835002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
28406ebbe77SMarcel Moolenaar 	}
28506ebbe77SMarcel Moolenaar 
286956d3333SMarcel Moolenaar 	return (error);
28706ebbe77SMarcel Moolenaar }
2887f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
28906ebbe77SMarcel Moolenaar 
29006ebbe77SMarcel Moolenaar int
291b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
29206ebbe77SMarcel Moolenaar {
2935002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
29406ebbe77SMarcel Moolenaar 	int error;
29506ebbe77SMarcel Moolenaar 
2965002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
297340f4a8dSEd Maste 		return (EINVAL);
29806ebbe77SMarcel Moolenaar 
29906ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3005002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
30106ebbe77SMarcel Moolenaar 		if (error)
302956d3333SMarcel Moolenaar 			return (error);
30306ebbe77SMarcel Moolenaar 	}
30406ebbe77SMarcel Moolenaar 
305b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
306956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
307956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
30806ebbe77SMarcel Moolenaar 
309956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3105002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
31106ebbe77SMarcel Moolenaar 	}
31206ebbe77SMarcel Moolenaar 
313956d3333SMarcel Moolenaar 	return (error);
314c21dee17SSøren Schmidt }
315c21dee17SSøren Schmidt 
3167f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
317c21dee17SSøren Schmidt int
318b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
319c21dee17SSøren Schmidt {
320b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3215002a60fSMarcel Moolenaar 	l_sigset_t mask;
322956d3333SMarcel Moolenaar 
323216af822SJohn Baldwin 	PROC_LOCK(p);
3244093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
325216af822SJohn Baldwin 	PROC_UNLOCK(p);
3264ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
327956d3333SMarcel Moolenaar 	return (0);
328c21dee17SSøren Schmidt }
329c21dee17SSøren Schmidt 
330c21dee17SSøren Schmidt int
331b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
332c21dee17SSøren Schmidt {
333b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3345002a60fSMarcel Moolenaar 	l_sigset_t lset;
335956d3333SMarcel Moolenaar 	sigset_t bset;
336c21dee17SSøren Schmidt 
337216af822SJohn Baldwin 	PROC_LOCK(p);
3384093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3394ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
340956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3414ab7403bSDmitry Chagin 	lset.__mask = args->mask;
342956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3434093529dSJeff Roberson 	td->td_sigmask = bset;
3444093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3454093529dSJeff Roberson 	signotify(td);
346216af822SJohn Baldwin 	PROC_UNLOCK(p);
347956d3333SMarcel Moolenaar 	return (0);
348c21dee17SSøren Schmidt }
349c21dee17SSøren Schmidt 
350c21dee17SSøren Schmidt int
351b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
352c21dee17SSøren Schmidt {
353b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
354956d3333SMarcel Moolenaar 	sigset_t bset;
3555002a60fSMarcel Moolenaar 	l_sigset_t lset;
3565002a60fSMarcel Moolenaar 	l_osigset_t mask;
357c21dee17SSøren Schmidt 
358216af822SJohn Baldwin 	PROC_LOCK(p);
3591d9c5696SJuli Mallett 	bset = p->p_siglist;
3604093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3614093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
362216af822SJohn Baldwin 	PROC_UNLOCK(p);
3639d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
3644ab7403bSDmitry Chagin 	mask = lset.__mask;
365956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
366c21dee17SSøren Schmidt }
3677f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
36817138b61SAlexander Leidinger 
36917138b61SAlexander Leidinger /*
37017138b61SAlexander Leidinger  * MPSAFE
37117138b61SAlexander Leidinger  */
37217138b61SAlexander Leidinger int
37317138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
37417138b61SAlexander Leidinger {
37517138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
37617138b61SAlexander Leidinger 	sigset_t bset;
37717138b61SAlexander Leidinger 	l_sigset_t lset;
37817138b61SAlexander Leidinger 
37917138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
380340f4a8dSEd Maste 		return (EINVAL);
38117138b61SAlexander Leidinger 		/* NOT REACHED */
38217138b61SAlexander Leidinger 
38317138b61SAlexander Leidinger 	PROC_LOCK(p);
38417138b61SAlexander Leidinger 	bset = p->p_siglist;
38517138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
38617138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
38717138b61SAlexander Leidinger 	PROC_UNLOCK(p);
38817138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
38917138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
39017138b61SAlexander Leidinger }
391c21dee17SSøren Schmidt 
392c9447c75SAlexander Leidinger int
393c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
394c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
395c9447c75SAlexander Leidinger {
396c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
3970f8dab45SDmitry Chagin 	struct l_timespec lts;
398*db4a1f33SDmitry Chagin 	int error;
399c9447c75SAlexander Leidinger 
400c9447c75SAlexander Leidinger 	if (args->timeout) {
4010f8dab45SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
402c9447c75SAlexander Leidinger 			return (error);
4030f8dab45SDmitry Chagin 		error = linux_to_native_timespec(&ts, &lts);
4040f8dab45SDmitry Chagin 		if (error != 0)
4050f8dab45SDmitry Chagin 			return (error);
406c9447c75SAlexander Leidinger 		tsa = &ts;
4070f8dab45SDmitry Chagin 	} else
4080f8dab45SDmitry Chagin 		tsa = NULL;
4090f8dab45SDmitry Chagin 
410*db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
411*db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
412*db4a1f33SDmitry Chagin }
413*db4a1f33SDmitry Chagin 
414*db4a1f33SDmitry Chagin static int
415*db4a1f33SDmitry Chagin linux_common_rt_sigtimedwait(struct thread *td, l_sigset_t *mask,
416*db4a1f33SDmitry Chagin     struct timespec *tsa, l_siginfo_t *ptr, l_size_t sigsetsize)
417*db4a1f33SDmitry Chagin {
418*db4a1f33SDmitry Chagin 	int error, sig;
419*db4a1f33SDmitry Chagin 	l_sigset_t lset;
420*db4a1f33SDmitry Chagin 	sigset_t bset;
421*db4a1f33SDmitry Chagin 	l_siginfo_t lsi;
422*db4a1f33SDmitry Chagin 	ksiginfo_t ksi;
423*db4a1f33SDmitry Chagin 
424*db4a1f33SDmitry Chagin 	if (sigsetsize != sizeof(l_sigset_t))
425*db4a1f33SDmitry Chagin 		return (EINVAL);
426*db4a1f33SDmitry Chagin 
427*db4a1f33SDmitry Chagin 	if ((error = copyin(mask, &lset, sizeof(lset))))
428*db4a1f33SDmitry Chagin 		return (error);
429*db4a1f33SDmitry Chagin 	linux_to_bsd_sigset(&lset, &bset);
430*db4a1f33SDmitry Chagin 
431*db4a1f33SDmitry Chagin 	ksiginfo_init(&ksi);
432f4e80108SDmitry Chagin 	error = kern_sigtimedwait(td, bset, &ksi, tsa);
433c9447c75SAlexander Leidinger 	if (error)
434c9447c75SAlexander Leidinger 		return (error);
435c9447c75SAlexander Leidinger 
436f4e80108SDmitry Chagin 	sig = bsd_to_linux_signal(ksi.ksi_signo);
437f3481dd9SDmitry Chagin 
438*db4a1f33SDmitry Chagin 	if (ptr) {
439f4e80108SDmitry Chagin 		memset(&lsi, 0, sizeof(lsi));
440f4e80108SDmitry Chagin 		siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
441*db4a1f33SDmitry Chagin 		error = copyout(&lsi, ptr, sizeof(lsi));
442c9447c75SAlexander Leidinger 	}
443f3481dd9SDmitry Chagin 	if (error == 0)
444f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
445c9447c75SAlexander Leidinger 
446c9447c75SAlexander Leidinger 	return (error);
447c9447c75SAlexander Leidinger }
448c9447c75SAlexander Leidinger 
449*db4a1f33SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
450*db4a1f33SDmitry Chagin int
451*db4a1f33SDmitry Chagin linux_rt_sigtimedwait_time64(struct thread *td,
452*db4a1f33SDmitry Chagin 	struct linux_rt_sigtimedwait_time64_args *args)
453*db4a1f33SDmitry Chagin {
454*db4a1f33SDmitry Chagin 	struct timespec ts, *tsa;
455*db4a1f33SDmitry Chagin 	struct l_timespec64 lts;
456*db4a1f33SDmitry Chagin 	int error;
457*db4a1f33SDmitry Chagin 
458*db4a1f33SDmitry Chagin 	if (args->timeout) {
459*db4a1f33SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
460*db4a1f33SDmitry Chagin 			return (error);
461*db4a1f33SDmitry Chagin 		error = linux_to_native_timespec64(&ts, &lts);
462*db4a1f33SDmitry Chagin 		if (error != 0)
463*db4a1f33SDmitry Chagin 			return (error);
464*db4a1f33SDmitry Chagin 		tsa = &ts;
465*db4a1f33SDmitry Chagin 	} else
466*db4a1f33SDmitry Chagin 		tsa = NULL;
467*db4a1f33SDmitry Chagin 
468*db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
469*db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
470*db4a1f33SDmitry Chagin }
471*db4a1f33SDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
472*db4a1f33SDmitry Chagin 
473c21dee17SSøren Schmidt int
474b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
475c21dee17SSøren Schmidt {
47634ad5ac2SEdward Tomasz Napierala 	int l_signum;
477c21dee17SSøren Schmidt 
478956d3333SMarcel Moolenaar 	/*
479956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
480956d3333SMarcel Moolenaar 	 */
48164742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
4829a6a64d3SDmitry Chagin 		return (EINVAL);
483956d3333SMarcel Moolenaar 
4844ab7403bSDmitry Chagin 	if (args->signum > 0)
48534ad5ac2SEdward Tomasz Napierala 		l_signum = linux_to_bsd_signal(args->signum);
486956d3333SMarcel Moolenaar 	else
48734ad5ac2SEdward Tomasz Napierala 		l_signum = 0;
488956d3333SMarcel Moolenaar 
48934ad5ac2SEdward Tomasz Napierala 	return (kern_kill(td, args->pid, l_signum));
490c21dee17SSøren Schmidt }
4919b44bfc5SAlexander Leidinger 
492aa8b2011SKonstantin Belousov static int
49381338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
494aa8b2011SKonstantin Belousov {
495aa8b2011SKonstantin Belousov 	struct proc *p;
496aa8b2011SKonstantin Belousov 	int error;
497aa8b2011SKonstantin Belousov 
49881338031SDmitry Chagin 	p = tdt->td_proc;
49981338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
50081338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
50114961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
50281338031SDmitry Chagin 
50381338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
50481338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
505aa8b2011SKonstantin Belousov 		goto out;
506aa8b2011SKonstantin Belousov 
50781338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
508aa8b2011SKonstantin Belousov 
509aa8b2011SKonstantin Belousov out:
510aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
511aa8b2011SKonstantin Belousov 	return (error);
512aa8b2011SKonstantin Belousov }
513aa8b2011SKonstantin Belousov 
5149b44bfc5SAlexander Leidinger int
5159b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5169b44bfc5SAlexander Leidinger {
51781338031SDmitry Chagin 	struct thread *tdt;
51881338031SDmitry Chagin 	ksiginfo_t ksi;
51981338031SDmitry Chagin 	int sig;
5209b44bfc5SAlexander Leidinger 
521aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
522aa8b2011SKonstantin Belousov 		return (EINVAL);
5239b44bfc5SAlexander Leidinger 
52481338031SDmitry Chagin 	/*
52581338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
52681338031SDmitry Chagin 	 */
52781338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
52881338031SDmitry Chagin 		return (EINVAL);
52981338031SDmitry Chagin 
5304ab7403bSDmitry Chagin 	if (args->sig > 0)
5314ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
53281338031SDmitry Chagin 	else
5334ab7403bSDmitry Chagin 		sig = 0;
53481338031SDmitry Chagin 
53581338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
53681338031SDmitry Chagin 	if (tdt == NULL)
53781338031SDmitry Chagin 		return (ESRCH);
53881338031SDmitry Chagin 
53981338031SDmitry Chagin 	ksiginfo_init(&ksi);
54081338031SDmitry Chagin 	ksi.ksi_signo = sig;
541fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
54281338031SDmitry Chagin 	ksi.ksi_errno = 0;
54381338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
54481338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
54581338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
5469b44bfc5SAlexander Leidinger }
5479b44bfc5SAlexander Leidinger 
54881338031SDmitry Chagin /*
54981338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
55081338031SDmitry Chagin  */
5519b44bfc5SAlexander Leidinger int
5529b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5539b44bfc5SAlexander Leidinger {
55481338031SDmitry Chagin 	struct thread *tdt;
55581338031SDmitry Chagin 	ksiginfo_t ksi;
55681338031SDmitry Chagin 	int sig;
55781338031SDmitry Chagin 
558aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
559aa8b2011SKonstantin Belousov 		return (EINVAL);
5609b44bfc5SAlexander Leidinger 
56181338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
56281338031SDmitry Chagin 		return (EINVAL);
56381338031SDmitry Chagin 
5644ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
56581338031SDmitry Chagin 
56681338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
56781338031SDmitry Chagin 	if (tdt == NULL)
56881338031SDmitry Chagin 		return (ESRCH);
56981338031SDmitry Chagin 
57081338031SDmitry Chagin 	ksiginfo_init(&ksi);
57181338031SDmitry Chagin 	ksi.ksi_signo = sig;
572fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
57381338031SDmitry Chagin 	ksi.ksi_errno = 0;
57481338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
57581338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
57681338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
577aa8b2011SKonstantin Belousov }
578aa8b2011SKonstantin Belousov 
579fe4ed1e7SDmitry Chagin static void
580fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
581fe4ed1e7SDmitry Chagin {
582fe4ed1e7SDmitry Chagin 
583fe4ed1e7SDmitry Chagin 	switch (si_code) {
584fe4ed1e7SDmitry Chagin 	case SI_USER:
585fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
586fe4ed1e7SDmitry Chagin 		break;
587fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
588fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
589fe4ed1e7SDmitry Chagin 		break;
590fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
591fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
592fe4ed1e7SDmitry Chagin 		break;
593fe4ed1e7SDmitry Chagin 	case SI_TIMER:
594fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
595fe4ed1e7SDmitry Chagin 		break;
596fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
597fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
598fe4ed1e7SDmitry Chagin 		break;
599fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
600fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
601fe4ed1e7SDmitry Chagin 		break;
602fe4ed1e7SDmitry Chagin 	case SI_LWP:
603fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
604fe4ed1e7SDmitry Chagin 		break;
605fe4ed1e7SDmitry Chagin 	default:
606fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
607fe4ed1e7SDmitry Chagin 		break;
608fe4ed1e7SDmitry Chagin 	}
609fe4ed1e7SDmitry Chagin }
610fe4ed1e7SDmitry Chagin 
611fe4ed1e7SDmitry Chagin void
612fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
613fe4ed1e7SDmitry Chagin {
614fe4ed1e7SDmitry Chagin 
615fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
616fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
617fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
618fe4ed1e7SDmitry Chagin 
619fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
620fe4ed1e7SDmitry Chagin 	case SI_LWP:
621fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
622fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
623fe4ed1e7SDmitry Chagin 		break;
624fe4ed1e7SDmitry Chagin 
625fe4ed1e7SDmitry Chagin 	case SI_TIMER:
626fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
627fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
628fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
629fe4ed1e7SDmitry Chagin 		break;
630fe4ed1e7SDmitry Chagin 
631fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
632fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
633fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
634fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
635fe4ed1e7SDmitry Chagin 		break;
636fe4ed1e7SDmitry Chagin 
637fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
638fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
639fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
640fe4ed1e7SDmitry Chagin 		break;
641fe4ed1e7SDmitry Chagin 
642fe4ed1e7SDmitry Chagin 	default:
643aa8b2011SKonstantin Belousov 		switch (sig) {
644aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
645aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
646fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
647aa8b2011SKonstantin Belousov 			break;
648fe4ed1e7SDmitry Chagin 
649aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
650fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
651fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
652fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
653fe4ed1e7SDmitry Chagin 
654fe4ed1e7SDmitry Chagin 			if (si->si_code == CLD_STOPPED)
6554ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
656fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
6574ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
658fe4ed1e7SDmitry Chagin 			else
659fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
660aa8b2011SKonstantin Belousov 			break;
661fe4ed1e7SDmitry Chagin 
662aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
663aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
664aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
665aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
666fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
667aa8b2011SKonstantin Belousov 			break;
668fe4ed1e7SDmitry Chagin 
669aa8b2011SKonstantin Belousov 		default:
670fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
671fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
672fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
673fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
674fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
675fe4ed1e7SDmitry Chagin 			}
676aa8b2011SKonstantin Belousov 			break;
677aa8b2011SKonstantin Belousov 		}
678fe4ed1e7SDmitry Chagin 		break;
67909d6cb0aSDmitry Chagin 	}
6809b44bfc5SAlexander Leidinger }
6817ac9766dSDmitry Chagin 
6829c1045ffSDmitry Chagin int
6839c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
6849c1045ffSDmitry Chagin     siginfo_t *si, int sig)
6857ac9766dSDmitry Chagin {
6867ac9766dSDmitry Chagin 
6879c1045ffSDmitry Chagin 	switch (lsi->lsi_code) {
6889c1045ffSDmitry Chagin 	case LINUX_SI_TKILL:
6899c1045ffSDmitry Chagin 		if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
6909c1045ffSDmitry Chagin 			linux_msg(td, "SI_TKILL forbidden since 2.6.39");
6919c1045ffSDmitry Chagin 			return (EPERM);
6929c1045ffSDmitry Chagin 		}
6939c1045ffSDmitry Chagin 		si->si_code = SI_LWP;
6949c1045ffSDmitry Chagin 	case LINUX_SI_QUEUE:
6959c1045ffSDmitry Chagin 		si->si_code = SI_QUEUE;
6969c1045ffSDmitry Chagin 		break;
6979c1045ffSDmitry Chagin 	case LINUX_SI_TIMER:
6989c1045ffSDmitry Chagin 		si->si_code = SI_TIMER;
6999c1045ffSDmitry Chagin 		break;
7009c1045ffSDmitry Chagin 	case LINUX_SI_MESGQ:
7019c1045ffSDmitry Chagin 		si->si_code = SI_MESGQ;
7029c1045ffSDmitry Chagin 		break;
7039c1045ffSDmitry Chagin 	case LINUX_SI_ASYNCIO:
7049c1045ffSDmitry Chagin 		si->si_code = SI_ASYNCIO;
7059c1045ffSDmitry Chagin 		break;
7069c1045ffSDmitry Chagin 	default:
7079c1045ffSDmitry Chagin 		si->si_code = lsi->lsi_code;
7089c1045ffSDmitry Chagin 		break;
7099c1045ffSDmitry Chagin 	}
7109c1045ffSDmitry Chagin 
7119c1045ffSDmitry Chagin 	si->si_signo = sig;
7129c1045ffSDmitry Chagin 	si->si_pid = td->td_proc->p_pid;
7139c1045ffSDmitry Chagin 	si->si_uid = td->td_ucred->cr_ruid;
7149c1045ffSDmitry Chagin 	si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
7159c1045ffSDmitry Chagin 	return (0);
7167ac9766dSDmitry Chagin }
7177ac9766dSDmitry Chagin 
7187ac9766dSDmitry Chagin int
7197ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7207ac9766dSDmitry Chagin {
7217ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7227ac9766dSDmitry Chagin 	struct proc *p;
7237ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7247ac9766dSDmitry Chagin 	int error;
7257ac9766dSDmitry Chagin 	int sig;
7267ac9766dSDmitry Chagin 
7277ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7287ac9766dSDmitry Chagin 		return (EINVAL);
7297ac9766dSDmitry Chagin 
7307ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7317ac9766dSDmitry Chagin 	if (error != 0)
7327ac9766dSDmitry Chagin 		return (error);
7337ac9766dSDmitry Chagin 
7347ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7359c1045ffSDmitry Chagin 		/* SI_USER, SI_KERNEL */
7367ac9766dSDmitry Chagin 		return (EPERM);
7377ac9766dSDmitry Chagin 
7384ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7399c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7409c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7419c1045ffSDmitry Chagin 	if (error != 0)
7429c1045ffSDmitry Chagin 		return (error);
7437ac9766dSDmitry Chagin 
7447ac9766dSDmitry Chagin 	error = ESRCH;
745537d0fb1SMateusz Guzik 	if ((p = pfind_any(args->pid)) != NULL) {
7467ac9766dSDmitry Chagin 		error = p_cansignal(td, p, sig);
7477ac9766dSDmitry Chagin 		if (error != 0) {
7487ac9766dSDmitry Chagin 			PROC_UNLOCK(p);
7497ac9766dSDmitry Chagin 			return (error);
7507ac9766dSDmitry Chagin 		}
7517ac9766dSDmitry Chagin 		error = tdsendsignal(p, NULL, sig, &ksi);
7527ac9766dSDmitry Chagin 		PROC_UNLOCK(p);
7537ac9766dSDmitry Chagin 	}
7547ac9766dSDmitry Chagin 
7557ac9766dSDmitry Chagin 	return (error);
7567ac9766dSDmitry Chagin }
757486a06bdSDmitry Chagin 
758486a06bdSDmitry Chagin int
759486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
760486a06bdSDmitry Chagin {
761486a06bdSDmitry Chagin 	l_siginfo_t linfo;
762486a06bdSDmitry Chagin 	struct thread *tds;
763486a06bdSDmitry Chagin 	ksiginfo_t ksi;
764486a06bdSDmitry Chagin 	int error;
765486a06bdSDmitry Chagin 	int sig;
766486a06bdSDmitry Chagin 
767486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
768486a06bdSDmitry Chagin 		return (EINVAL);
769486a06bdSDmitry Chagin 
770486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
771486a06bdSDmitry Chagin 	if (error != 0)
772486a06bdSDmitry Chagin 		return (error);
773486a06bdSDmitry Chagin 
774486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
775486a06bdSDmitry Chagin 		return (EPERM);
776486a06bdSDmitry Chagin 
7779c1045ffSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7789c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7799c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7809c1045ffSDmitry Chagin 	if (error != 0)
7819c1045ffSDmitry Chagin 		return (error);
7829c1045ffSDmitry Chagin 
783486a06bdSDmitry Chagin 	tds = linux_tdfind(td, args->tid, args->tgid);
784486a06bdSDmitry Chagin 	if (tds == NULL)
785486a06bdSDmitry Chagin 		return (ESRCH);
786486a06bdSDmitry Chagin 
787486a06bdSDmitry Chagin 	return (linux_do_tkill(td, tds, &ksi));
788486a06bdSDmitry Chagin }
789