xref: /freebsd/sys/compat/linux/linux_signal.c (revision 2722e515ac8d0232cd80e5e8848715e27d222902)
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>
3430c6d982SEdward Tomasz Napierala #include <sys/ktr.h>
35fb919e4dSMark Murray #include <sys/lock.h>
36fb919e4dSMark Murray #include <sys/mutex.h>
3729ddc19bSAlexander Leidinger #include <sys/sx.h>
38c21dee17SSøren Schmidt #include <sys/proc.h>
39c21dee17SSøren Schmidt #include <sys/signalvar.h>
40206a5d3aSIan Dowse #include <sys/syscallsubr.h>
41fb919e4dSMark Murray #include <sys/sysproto.h>
42c21dee17SSøren Schmidt 
43aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
44aa8b2011SKonstantin Belousov 
45aefce619SRuslan Ermilov #include "opt_compat.h"
46aefce619SRuslan Ermilov 
471997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
484af27623STim J. Robbins #include <machine/../linux32/linux.h>
494af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
501997c537SDavid E. O'Brien #else
511997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
521997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
534af27623STim J. Robbins #endif
549c1045ffSDmitry Chagin #include <compat/linux/linux_mib.h>
55ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
560f8dab45SDmitry Chagin #include <compat/linux/linux_timer.h>
57ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
589b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
5981338031SDmitry Chagin #include <compat/linux/linux_misc.h>
6081338031SDmitry Chagin 
616201a50dSDmitry Chagin static int	linux_pksignal(struct thread *td, int pid, int sig,
6281338031SDmitry Chagin 		    ksiginfo_t *ksi);
636201a50dSDmitry Chagin static int	linux_psignal(struct thread *td, int pid, int sig);
646201a50dSDmitry Chagin static int	linux_tdksignal(struct thread *td, lwpid_t tid,
656201a50dSDmitry Chagin 		    int tgid, int sig, ksiginfo_t *ksi);
666201a50dSDmitry Chagin static int	linux_tdsignal(struct thread *td, lwpid_t tid,
676201a50dSDmitry Chagin 		    int tgid, int sig);
68a6f85b12SDmitry Chagin static void	sicode_to_lsicode(int sig, int si_code, int *lsi_code);
69db4a1f33SDmitry Chagin static int	linux_common_rt_sigtimedwait(struct thread *,
70db4a1f33SDmitry Chagin 		    l_sigset_t *, struct timespec *, l_siginfo_t *,
71db4a1f33SDmitry Chagin 		    l_size_t);
72fe4ed1e7SDmitry Chagin 
73a1ebcbfbSPeter Wemm static void
745002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
75d66a5066SPeter Wemm {
76d5629eb2SEdward Tomasz Napierala 	unsigned long flags;
77956d3333SMarcel Moolenaar 
78956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
794af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
80d66a5066SPeter Wemm 	bsa->sa_flags = 0;
81d5629eb2SEdward Tomasz Napierala 
82d5629eb2SEdward Tomasz Napierala 	flags = lsa->lsa_flags;
83d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
84d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDSTOP;
85d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
86d5629eb2SEdward Tomasz Napierala 	}
87d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
88d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOCLDWAIT;
8906ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
90d5629eb2SEdward Tomasz Napierala 	}
91d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
92d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_SIGINFO;
9306ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
94d5629eb2SEdward Tomasz Napierala #ifdef notyet
95d5629eb2SEdward Tomasz Napierala 		/*
96d5629eb2SEdward Tomasz Napierala 		 * XXX: We seem to be missing code to convert
97d5629eb2SEdward Tomasz Napierala 		 *      some of the fields in ucontext_t.
98d5629eb2SEdward Tomasz Napierala 		 */
99d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread,
100d5629eb2SEdward Tomasz Napierala 		    "partially unsupported sigaction flag SA_SIGINFO");
101d5629eb2SEdward Tomasz Napierala #endif
102d5629eb2SEdward Tomasz Napierala 	}
103d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTORER) {
104d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTORER;
1053eaf271dSEdward Tomasz Napierala 		/*
1063eaf271dSEdward Tomasz Napierala 		 * We ignore the lsa_restorer and always use our own signal
1073eaf271dSEdward Tomasz Napierala 		 * trampoline instead.  It looks like SA_RESTORER is obsolete
1083eaf271dSEdward Tomasz Napierala 		 * in Linux too - it doesn't seem to be used at all on arm64.
1093eaf271dSEdward Tomasz Napierala 		 * In any case: see Linux sigreturn(2).
1103eaf271dSEdward Tomasz Napierala 		 */
111d5629eb2SEdward Tomasz Napierala 	}
112d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
113d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONSTACK;
114d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
115d5629eb2SEdward Tomasz Napierala 	}
116d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
117d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_RESTART;
118d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
119d5629eb2SEdward Tomasz Napierala 	}
1209bc42c18SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
1219bc42c18SEdward Tomasz Napierala 		flags &= ~LINUX_SA_INTERRUPT;
1229bc42c18SEdward Tomasz Napierala 		/* Documented to be a "historical no-op". */
1239bc42c18SEdward Tomasz Napierala 	}
124d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
125d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_ONESHOT;
126d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
127d5629eb2SEdward Tomasz Napierala 	}
128d5629eb2SEdward Tomasz Napierala 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
129d5629eb2SEdward Tomasz Napierala 		flags &= ~LINUX_SA_NOMASK;
130d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
131d66a5066SPeter Wemm 	}
132d66a5066SPeter Wemm 
133d5629eb2SEdward Tomasz Napierala 	if (flags != 0)
134d5629eb2SEdward Tomasz Napierala 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
135d5629eb2SEdward Tomasz Napierala }
136d5629eb2SEdward Tomasz Napierala 
137a1ebcbfbSPeter Wemm static void
1385002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
139d66a5066SPeter Wemm {
140956d3333SMarcel Moolenaar 
141956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1421997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1434af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1444af27623STim J. Robbins #else
1458f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1464af27623STim J. Robbins #endif
1474af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1488f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
149d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1508f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
15106ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
15206ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
15306ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
15406ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
155d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1568f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
157d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1588f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
159d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1608f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
161d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1628f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
163d66a5066SPeter Wemm }
164c21dee17SSøren Schmidt 
165ba9ef45bSMarcel Moolenaar int
166b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1675002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
16806ebbe77SMarcel Moolenaar {
169206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
170206a5d3aSIan Dowse 	int error, sig;
17106ebbe77SMarcel Moolenaar 
172687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
173956d3333SMarcel Moolenaar 		return (EINVAL);
17406ebbe77SMarcel Moolenaar 
175206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
176956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
177206a5d3aSIan Dowse 		nsa = &act;
178ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
179206a5d3aSIan Dowse 	} else
18006ebbe77SMarcel Moolenaar 		nsa = NULL;
1814ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(linux_sig);
182956d3333SMarcel Moolenaar 
183206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
18455731437SDmitry Chagin 	if (error != 0)
185956d3333SMarcel Moolenaar 		return (error);
18606ebbe77SMarcel Moolenaar 
187ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
188ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
18906ebbe77SMarcel Moolenaar 
190956d3333SMarcel Moolenaar 	return (0);
19106ebbe77SMarcel Moolenaar }
19206ebbe77SMarcel Moolenaar 
19330c6d982SEdward Tomasz Napierala int
19430c6d982SEdward Tomasz Napierala linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
19530c6d982SEdward Tomasz Napierala {
19630c6d982SEdward Tomasz Napierala 	stack_t ss, oss;
19730c6d982SEdward Tomasz Napierala 	l_stack_t lss;
19830c6d982SEdward Tomasz Napierala 	int error;
19930c6d982SEdward Tomasz Napierala 
20030c6d982SEdward Tomasz Napierala 	memset(&lss, 0, sizeof(lss));
20130c6d982SEdward Tomasz Napierala 	LINUX_CTR2(sigaltstack, "%p, %p", uap->uss, uap->uoss);
20230c6d982SEdward Tomasz Napierala 
20330c6d982SEdward Tomasz Napierala 	if (uap->uss != NULL) {
204*2722e515SDmitry Chagin 		error = copyin(uap->uss, &lss, sizeof(lss));
20530c6d982SEdward Tomasz Napierala 		if (error != 0)
20630c6d982SEdward Tomasz Napierala 			return (error);
20730c6d982SEdward Tomasz Napierala 
20830c6d982SEdward Tomasz Napierala 		ss.ss_sp = PTRIN(lss.ss_sp);
20930c6d982SEdward Tomasz Napierala 		ss.ss_size = lss.ss_size;
21030c6d982SEdward Tomasz Napierala 		ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
21130c6d982SEdward Tomasz Napierala 	}
21230c6d982SEdward Tomasz Napierala 	error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL,
21330c6d982SEdward Tomasz Napierala 	    (uap->uoss != NULL) ? &oss : NULL);
21430c6d982SEdward Tomasz Napierala 	if (error == 0 && uap->uoss != NULL) {
21530c6d982SEdward Tomasz Napierala 		lss.ss_sp = PTROUT(oss.ss_sp);
21630c6d982SEdward Tomasz Napierala 		lss.ss_size = oss.ss_size;
21730c6d982SEdward Tomasz Napierala 		lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
218*2722e515SDmitry Chagin 		error = copyout(&lss, uap->uoss, sizeof(lss));
21930c6d982SEdward Tomasz Napierala 	}
22030c6d982SEdward Tomasz Napierala 
22130c6d982SEdward Tomasz Napierala 	return (error);
22230c6d982SEdward Tomasz Napierala }
22330c6d982SEdward Tomasz Napierala 
2247f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
225c21dee17SSøren Schmidt int
226b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
227d66a5066SPeter Wemm {
2285002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
229d66a5066SPeter Wemm 	int error;
230d66a5066SPeter Wemm 
23106ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
23206ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
233956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
234d66a5066SPeter Wemm 
235b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
2364af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
237d66a5066SPeter Wemm 
238956d3333SMarcel Moolenaar 	return (error);
239d66a5066SPeter Wemm }
2407f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
241d66a5066SPeter Wemm 
242c21dee17SSøren Schmidt int
243b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
244c21dee17SSøren Schmidt {
2455002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
24606ebbe77SMarcel Moolenaar 	int error;
247c21dee17SSøren Schmidt 
2485002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
249956d3333SMarcel Moolenaar 		return (EINVAL);
25006ebbe77SMarcel Moolenaar 
251956d3333SMarcel Moolenaar 	if (args->act != NULL) {
252*2722e515SDmitry Chagin 		error = copyin(args->act, &nsa, sizeof(nsa));
25355731437SDmitry Chagin 		if (error != 0)
254956d3333SMarcel Moolenaar 			return (error);
25506ebbe77SMarcel Moolenaar 	}
25606ebbe77SMarcel Moolenaar 
257b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
25806ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
25906ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
26006ebbe77SMarcel Moolenaar 
26155731437SDmitry Chagin 	if (args->oact != NULL && error == 0)
262*2722e515SDmitry Chagin 		error = copyout(&osa, args->oact, sizeof(osa));
26306ebbe77SMarcel Moolenaar 
264956d3333SMarcel Moolenaar 	return (error);
26506ebbe77SMarcel Moolenaar }
26606ebbe77SMarcel Moolenaar 
26706ebbe77SMarcel Moolenaar static int
2685e872c27SDmitry Chagin linux_do_sigprocmask(struct thread *td, int how, sigset_t *new,
2695002a60fSMarcel Moolenaar 		     l_sigset_t *old)
27006ebbe77SMarcel Moolenaar {
2715e872c27SDmitry Chagin 	sigset_t omask;
272216af822SJohn Baldwin 	int error;
27306ebbe77SMarcel Moolenaar 
274b40ce416SJulian Elischer 	td->td_retval[0] = 0;
275d66a5066SPeter Wemm 
27619dde5cdSJohn Baldwin 	switch (how) {
27719dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
27819dde5cdSJohn Baldwin 		how = SIG_BLOCK;
27919dde5cdSJohn Baldwin 		break;
28019dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
28119dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
28219dde5cdSJohn Baldwin 		break;
28319dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
28419dde5cdSJohn Baldwin 		how = SIG_SETMASK;
28519dde5cdSJohn Baldwin 		break;
28619dde5cdSJohn Baldwin 	default:
28719dde5cdSJohn Baldwin 		return (EINVAL);
28819dde5cdSJohn Baldwin 	}
2895e872c27SDmitry Chagin 	error = kern_sigprocmask(td, how, new, &omask, 0);
2902f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
291fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
29206ebbe77SMarcel Moolenaar 
293956d3333SMarcel Moolenaar 	return (error);
29406ebbe77SMarcel Moolenaar }
29506ebbe77SMarcel Moolenaar 
2967f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
29706ebbe77SMarcel Moolenaar int
298b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
29906ebbe77SMarcel Moolenaar {
3005002a60fSMarcel Moolenaar 	l_osigset_t mask;
3015e872c27SDmitry Chagin 	l_sigset_t lset, oset;
3025e872c27SDmitry Chagin 	sigset_t set;
30306ebbe77SMarcel Moolenaar 	int error;
30406ebbe77SMarcel Moolenaar 
30506ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
306*2722e515SDmitry Chagin 		error = copyin(args->mask, &mask, sizeof(mask));
30755731437SDmitry Chagin 		if (error != 0)
308956d3333SMarcel Moolenaar 			return (error);
3095e872c27SDmitry Chagin 		LINUX_SIGEMPTYSET(lset);
3105e872c27SDmitry Chagin 		lset.__mask = mask;
3115e872c27SDmitry Chagin 		linux_to_bsd_sigset(&lset, &set);
31206ebbe77SMarcel Moolenaar 	}
31306ebbe77SMarcel Moolenaar 
314b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
315956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
316956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
31706ebbe77SMarcel Moolenaar 
31855731437SDmitry Chagin 	if (args->omask != NULL && error == 0) {
3194ab7403bSDmitry Chagin 		mask = oset.__mask;
320*2722e515SDmitry Chagin 		error = copyout(&mask, args->omask, sizeof(mask));
32106ebbe77SMarcel Moolenaar 	}
32206ebbe77SMarcel Moolenaar 
323956d3333SMarcel Moolenaar 	return (error);
32406ebbe77SMarcel Moolenaar }
3257f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
32606ebbe77SMarcel Moolenaar 
32706ebbe77SMarcel Moolenaar int
328b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
32906ebbe77SMarcel Moolenaar {
3305e872c27SDmitry Chagin 	l_sigset_t oset;
3315e872c27SDmitry Chagin 	sigset_t set, *pset;
33206ebbe77SMarcel Moolenaar 	int error;
33306ebbe77SMarcel Moolenaar 
3345e872c27SDmitry Chagin 	error = linux_copyin_sigset(args->mask, args->sigsetsize,
3355e872c27SDmitry Chagin 	    &set, &pset);
3365e872c27SDmitry Chagin 	if (error != 0)
337340f4a8dSEd Maste 		return (EINVAL);
33806ebbe77SMarcel Moolenaar 
3395e872c27SDmitry Chagin 	error = linux_do_sigprocmask(td, args->how, pset,
340956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
34106ebbe77SMarcel Moolenaar 
34255731437SDmitry Chagin 	if (args->omask != NULL && error == 0)
343*2722e515SDmitry Chagin 		error = copyout(&oset, args->omask, sizeof(oset));
34406ebbe77SMarcel Moolenaar 
345956d3333SMarcel Moolenaar 	return (error);
346c21dee17SSøren Schmidt }
347c21dee17SSøren Schmidt 
3487f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
349c21dee17SSøren Schmidt int
350b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
351c21dee17SSøren Schmidt {
352b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3535002a60fSMarcel Moolenaar 	l_sigset_t mask;
354956d3333SMarcel Moolenaar 
355216af822SJohn Baldwin 	PROC_LOCK(p);
3564093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
357216af822SJohn Baldwin 	PROC_UNLOCK(p);
3584ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
359956d3333SMarcel Moolenaar 	return (0);
360c21dee17SSøren Schmidt }
361c21dee17SSøren Schmidt 
362c21dee17SSøren Schmidt int
363b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
364c21dee17SSøren Schmidt {
365b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3665002a60fSMarcel Moolenaar 	l_sigset_t lset;
367956d3333SMarcel Moolenaar 	sigset_t bset;
368c21dee17SSøren Schmidt 
369216af822SJohn Baldwin 	PROC_LOCK(p);
3704093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3714ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
372956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3734ab7403bSDmitry Chagin 	lset.__mask = args->mask;
374956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3754093529dSJeff Roberson 	td->td_sigmask = bset;
3764093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3774093529dSJeff Roberson 	signotify(td);
378216af822SJohn Baldwin 	PROC_UNLOCK(p);
379956d3333SMarcel Moolenaar 	return (0);
380c21dee17SSøren Schmidt }
381c21dee17SSøren Schmidt 
382c21dee17SSøren Schmidt int
383b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
384c21dee17SSøren Schmidt {
385b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
386956d3333SMarcel Moolenaar 	sigset_t bset;
3875002a60fSMarcel Moolenaar 	l_sigset_t lset;
3885002a60fSMarcel Moolenaar 	l_osigset_t mask;
389c21dee17SSøren Schmidt 
390216af822SJohn Baldwin 	PROC_LOCK(p);
3911d9c5696SJuli Mallett 	bset = p->p_siglist;
3924093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3934093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
394216af822SJohn Baldwin 	PROC_UNLOCK(p);
3959d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
3964ab7403bSDmitry Chagin 	mask = lset.__mask;
397956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
398c21dee17SSøren Schmidt }
3997f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
40017138b61SAlexander Leidinger 
40117138b61SAlexander Leidinger /*
40217138b61SAlexander Leidinger  * MPSAFE
40317138b61SAlexander Leidinger  */
40417138b61SAlexander Leidinger int
40517138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
40617138b61SAlexander Leidinger {
40717138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
40817138b61SAlexander Leidinger 	sigset_t bset;
40917138b61SAlexander Leidinger 	l_sigset_t lset;
41017138b61SAlexander Leidinger 
41117138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
412340f4a8dSEd Maste 		return (EINVAL);
41317138b61SAlexander Leidinger 		/* NOT REACHED */
41417138b61SAlexander Leidinger 
41517138b61SAlexander Leidinger 	PROC_LOCK(p);
41617138b61SAlexander Leidinger 	bset = p->p_siglist;
41717138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
41817138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
41917138b61SAlexander Leidinger 	PROC_UNLOCK(p);
42017138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
42117138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
42217138b61SAlexander Leidinger }
423c21dee17SSøren Schmidt 
424c9447c75SAlexander Leidinger int
425c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
426c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
427c9447c75SAlexander Leidinger {
428c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
429db4a1f33SDmitry Chagin 	int error;
430c9447c75SAlexander Leidinger 
431c9447c75SAlexander Leidinger 	if (args->timeout) {
432707e567aSDmitry Chagin 		error = linux_get_timespec(&ts, args->timeout);
4330f8dab45SDmitry Chagin 		if (error != 0)
4340f8dab45SDmitry Chagin 			return (error);
435c9447c75SAlexander Leidinger 		tsa = &ts;
4360f8dab45SDmitry Chagin 	} else
4370f8dab45SDmitry Chagin 		tsa = NULL;
4380f8dab45SDmitry Chagin 
439db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
440db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
441db4a1f33SDmitry Chagin }
442db4a1f33SDmitry Chagin 
443db4a1f33SDmitry Chagin static int
444db4a1f33SDmitry Chagin linux_common_rt_sigtimedwait(struct thread *td, l_sigset_t *mask,
445db4a1f33SDmitry Chagin     struct timespec *tsa, l_siginfo_t *ptr, l_size_t sigsetsize)
446db4a1f33SDmitry Chagin {
447db4a1f33SDmitry Chagin 	int error, sig;
448db4a1f33SDmitry Chagin 	sigset_t bset;
449db4a1f33SDmitry Chagin 	l_siginfo_t lsi;
450db4a1f33SDmitry Chagin 	ksiginfo_t ksi;
451db4a1f33SDmitry Chagin 
4523923e632SDmitry Chagin 	error = linux_copyin_sigset(mask, sigsetsize, &bset, NULL);
4533923e632SDmitry Chagin 	if (error != 0)
454db4a1f33SDmitry Chagin 		return (error);
455db4a1f33SDmitry Chagin 
456db4a1f33SDmitry Chagin 	ksiginfo_init(&ksi);
457f4e80108SDmitry Chagin 	error = kern_sigtimedwait(td, bset, &ksi, tsa);
45855731437SDmitry Chagin 	if (error != 0)
459c9447c75SAlexander Leidinger 		return (error);
460c9447c75SAlexander Leidinger 
461f4e80108SDmitry Chagin 	sig = bsd_to_linux_signal(ksi.ksi_signo);
462f3481dd9SDmitry Chagin 
463db4a1f33SDmitry Chagin 	if (ptr) {
464f4e80108SDmitry Chagin 		memset(&lsi, 0, sizeof(lsi));
465f4e80108SDmitry Chagin 		siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
466db4a1f33SDmitry Chagin 		error = copyout(&lsi, ptr, sizeof(lsi));
467c9447c75SAlexander Leidinger 	}
468f3481dd9SDmitry Chagin 	if (error == 0)
469f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
470c9447c75SAlexander Leidinger 
471c9447c75SAlexander Leidinger 	return (error);
472c9447c75SAlexander Leidinger }
473c9447c75SAlexander Leidinger 
474db4a1f33SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
475db4a1f33SDmitry Chagin int
476db4a1f33SDmitry Chagin linux_rt_sigtimedwait_time64(struct thread *td,
477db4a1f33SDmitry Chagin 	struct linux_rt_sigtimedwait_time64_args *args)
478db4a1f33SDmitry Chagin {
479db4a1f33SDmitry Chagin 	struct timespec ts, *tsa;
480db4a1f33SDmitry Chagin 	int error;
481db4a1f33SDmitry Chagin 
482db4a1f33SDmitry Chagin 	if (args->timeout) {
483707e567aSDmitry Chagin 		error = linux_get_timespec64(&ts, args->timeout);
484db4a1f33SDmitry Chagin 		if (error != 0)
485db4a1f33SDmitry Chagin 			return (error);
486db4a1f33SDmitry Chagin 		tsa = &ts;
487db4a1f33SDmitry Chagin 	} else
488db4a1f33SDmitry Chagin 		tsa = NULL;
489db4a1f33SDmitry Chagin 
490db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
491db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
492db4a1f33SDmitry Chagin }
493db4a1f33SDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
494db4a1f33SDmitry Chagin 
495c21dee17SSøren Schmidt int
496b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
497c21dee17SSøren Schmidt {
4986201a50dSDmitry Chagin 	int sig;
499c21dee17SSøren Schmidt 
500956d3333SMarcel Moolenaar 	/*
501956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
502956d3333SMarcel Moolenaar 	 */
50364742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5049a6a64d3SDmitry Chagin 		return (EINVAL);
505956d3333SMarcel Moolenaar 
5064ab7403bSDmitry Chagin 	if (args->signum > 0)
5076201a50dSDmitry Chagin 		sig = linux_to_bsd_signal(args->signum);
508956d3333SMarcel Moolenaar 	else
5096201a50dSDmitry Chagin 		sig = 0;
510956d3333SMarcel Moolenaar 
5116201a50dSDmitry Chagin 	if (args->pid > PID_MAX)
5126201a50dSDmitry Chagin 		return (linux_psignal(td, args->pid, sig));
5136201a50dSDmitry Chagin 	else
5146201a50dSDmitry Chagin 		return (kern_kill(td, args->pid, sig));
515aa8b2011SKonstantin Belousov }
516aa8b2011SKonstantin Belousov 
5179b44bfc5SAlexander Leidinger int
5189b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5199b44bfc5SAlexander Leidinger {
52081338031SDmitry Chagin 	int sig;
5219b44bfc5SAlexander Leidinger 
522aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
523aa8b2011SKonstantin Belousov 		return (EINVAL);
5249b44bfc5SAlexander Leidinger 
52581338031SDmitry Chagin 	/*
52681338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
52781338031SDmitry Chagin 	 */
52881338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
52981338031SDmitry Chagin 		return (EINVAL);
53081338031SDmitry Chagin 
5314ab7403bSDmitry Chagin 	if (args->sig > 0)
5324ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
53381338031SDmitry Chagin 	else
5344ab7403bSDmitry Chagin 		sig = 0;
53581338031SDmitry Chagin 
5366201a50dSDmitry Chagin 	return (linux_tdsignal(td, args->pid, args->tgid, sig));
5379b44bfc5SAlexander Leidinger }
5389b44bfc5SAlexander Leidinger 
53981338031SDmitry Chagin /*
54081338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
54181338031SDmitry Chagin  */
5429b44bfc5SAlexander Leidinger int
5439b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5449b44bfc5SAlexander Leidinger {
54581338031SDmitry Chagin 	int sig;
54681338031SDmitry Chagin 
547aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
548aa8b2011SKonstantin Belousov 		return (EINVAL);
5499b44bfc5SAlexander Leidinger 
55081338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
55181338031SDmitry Chagin 		return (EINVAL);
55281338031SDmitry Chagin 
5534ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
55481338031SDmitry Chagin 
5556201a50dSDmitry Chagin 	return (linux_tdsignal(td, args->tid, -1, sig));
556aa8b2011SKonstantin Belousov }
557aa8b2011SKonstantin Belousov 
558a6f85b12SDmitry Chagin static int
559a6f85b12SDmitry Chagin sigfpe_sicode2lsicode(int si_code)
560a6f85b12SDmitry Chagin {
561a6f85b12SDmitry Chagin 
562a6f85b12SDmitry Chagin 	switch (si_code) {
563a6f85b12SDmitry Chagin 	case FPE_INTOVF:
564a6f85b12SDmitry Chagin 		return (LINUX_FPE_INTOVF);
565a6f85b12SDmitry Chagin 	case FPE_INTDIV:
566a6f85b12SDmitry Chagin 		return (LINUX_FPE_INTDIV);
567a6f85b12SDmitry Chagin 	case FPE_FLTIDO:
568a6f85b12SDmitry Chagin 		return (LINUX_FPE_FLTUNK);
569a6f85b12SDmitry Chagin 	default:
570a6f85b12SDmitry Chagin 		return (si_code);
571a6f85b12SDmitry Chagin 	}
572a6f85b12SDmitry Chagin }
573a6f85b12SDmitry Chagin 
574a6f85b12SDmitry Chagin static int
575a6f85b12SDmitry Chagin sigbus_sicode2lsicode(int si_code)
576a6f85b12SDmitry Chagin {
577a6f85b12SDmitry Chagin 
578a6f85b12SDmitry Chagin 	switch (si_code) {
579a6f85b12SDmitry Chagin 	case BUS_OOMERR:
580a6f85b12SDmitry Chagin 		return (LINUX_BUS_MCEERR_AR);
581a6f85b12SDmitry Chagin 	default:
582a6f85b12SDmitry Chagin 		return (si_code);
583a6f85b12SDmitry Chagin 	}
584a6f85b12SDmitry Chagin }
585a6f85b12SDmitry Chagin 
586a6f85b12SDmitry Chagin static int
587a6f85b12SDmitry Chagin sigsegv_sicode2lsicode(int si_code)
588a6f85b12SDmitry Chagin {
589a6f85b12SDmitry Chagin 
590a6f85b12SDmitry Chagin 	switch (si_code) {
591a6f85b12SDmitry Chagin 	case SEGV_PKUERR:
592a6f85b12SDmitry Chagin 		return (LINUX_SEGV_PKUERR);
593a6f85b12SDmitry Chagin 	default:
594a6f85b12SDmitry Chagin 		return (si_code);
595a6f85b12SDmitry Chagin 	}
596a6f85b12SDmitry Chagin }
597a6f85b12SDmitry Chagin 
598a6f85b12SDmitry Chagin static int
599a6f85b12SDmitry Chagin sigtrap_sicode2lsicode(int si_code)
600a6f85b12SDmitry Chagin {
601a6f85b12SDmitry Chagin 
602a6f85b12SDmitry Chagin 	switch (si_code) {
603a6f85b12SDmitry Chagin 	case TRAP_DTRACE:
604a6f85b12SDmitry Chagin 		return (LINUX_TRAP_TRACE);
605a6f85b12SDmitry Chagin 	case TRAP_CAP:
606a6f85b12SDmitry Chagin 		return (LINUX_TRAP_UNK);
607a6f85b12SDmitry Chagin 	default:
608a6f85b12SDmitry Chagin 		return (si_code);
609a6f85b12SDmitry Chagin 	}
610a6f85b12SDmitry Chagin }
611a6f85b12SDmitry Chagin 
612fe4ed1e7SDmitry Chagin static void
613a6f85b12SDmitry Chagin sicode_to_lsicode(int sig, int si_code, int *lsi_code)
614fe4ed1e7SDmitry Chagin {
615fe4ed1e7SDmitry Chagin 
616fe4ed1e7SDmitry Chagin 	switch (si_code) {
617fe4ed1e7SDmitry Chagin 	case SI_USER:
618fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
619fe4ed1e7SDmitry Chagin 		break;
620fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
621fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
622fe4ed1e7SDmitry Chagin 		break;
623fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
624fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
625fe4ed1e7SDmitry Chagin 		break;
626fe4ed1e7SDmitry Chagin 	case SI_TIMER:
627fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
628fe4ed1e7SDmitry Chagin 		break;
629fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
630fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
631fe4ed1e7SDmitry Chagin 		break;
632fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
633fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
634fe4ed1e7SDmitry Chagin 		break;
635fe4ed1e7SDmitry Chagin 	case SI_LWP:
636fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
637fe4ed1e7SDmitry Chagin 		break;
638fe4ed1e7SDmitry Chagin 	default:
639a6f85b12SDmitry Chagin 		switch (sig) {
640a6f85b12SDmitry Chagin 		case LINUX_SIGFPE:
641a6f85b12SDmitry Chagin 			*lsi_code = sigfpe_sicode2lsicode(si_code);
642a6f85b12SDmitry Chagin 			break;
643a6f85b12SDmitry Chagin 		case LINUX_SIGBUS:
644a6f85b12SDmitry Chagin 			*lsi_code = sigbus_sicode2lsicode(si_code);
645a6f85b12SDmitry Chagin 			break;
646a6f85b12SDmitry Chagin 		case LINUX_SIGSEGV:
647a6f85b12SDmitry Chagin 			*lsi_code = sigsegv_sicode2lsicode(si_code);
648a6f85b12SDmitry Chagin 			break;
649a6f85b12SDmitry Chagin 		case LINUX_SIGTRAP:
650a6f85b12SDmitry Chagin 			*lsi_code = sigtrap_sicode2lsicode(si_code);
651a6f85b12SDmitry Chagin 			break;
652a6f85b12SDmitry Chagin 		default:
653fe4ed1e7SDmitry Chagin 			*lsi_code = si_code;
654fe4ed1e7SDmitry Chagin 			break;
655fe4ed1e7SDmitry Chagin 		}
656a6f85b12SDmitry Chagin 		break;
657a6f85b12SDmitry Chagin 	}
658fe4ed1e7SDmitry Chagin }
659fe4ed1e7SDmitry Chagin 
660fe4ed1e7SDmitry Chagin void
661fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
662fe4ed1e7SDmitry Chagin {
663fe4ed1e7SDmitry Chagin 
664fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
665fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
666a6f85b12SDmitry Chagin 	sicode_to_lsicode(sig, si->si_code, &lsi->lsi_code);
667fe4ed1e7SDmitry Chagin 
668fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
669fe4ed1e7SDmitry Chagin 	case SI_LWP:
670fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
671fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
672fe4ed1e7SDmitry Chagin 		break;
673fe4ed1e7SDmitry Chagin 
674fe4ed1e7SDmitry Chagin 	case SI_TIMER:
675fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
676fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
677fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
678fe4ed1e7SDmitry Chagin 		break;
679fe4ed1e7SDmitry Chagin 
680fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
681fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
682fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
683fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
684fe4ed1e7SDmitry Chagin 		break;
685fe4ed1e7SDmitry Chagin 
686fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
687fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
688fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
689fe4ed1e7SDmitry Chagin 		break;
690fe4ed1e7SDmitry Chagin 
691fe4ed1e7SDmitry Chagin 	default:
692aa8b2011SKonstantin Belousov 		switch (sig) {
693aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
694aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
695fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
696aa8b2011SKonstantin Belousov 			break;
697fe4ed1e7SDmitry Chagin 
698aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
699fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
700fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
701fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
702fe4ed1e7SDmitry Chagin 
703c8c93b15SEdward Tomasz Napierala 			if (si->si_code == CLD_STOPPED || si->si_code == CLD_KILLED)
7044ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
705fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
7064ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
707fe4ed1e7SDmitry Chagin 			else
708fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
709aa8b2011SKonstantin Belousov 			break;
710fe4ed1e7SDmitry Chagin 
711aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
712aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
713aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
714aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
715fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
716aa8b2011SKonstantin Belousov 			break;
717fe4ed1e7SDmitry Chagin 
718aa8b2011SKonstantin Belousov 		default:
719fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
720fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
721fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
722fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
723fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
724fe4ed1e7SDmitry Chagin 			}
725aa8b2011SKonstantin Belousov 			break;
726aa8b2011SKonstantin Belousov 		}
727fe4ed1e7SDmitry Chagin 		break;
72809d6cb0aSDmitry Chagin 	}
7299b44bfc5SAlexander Leidinger }
7307ac9766dSDmitry Chagin 
7319c1045ffSDmitry Chagin int
7329c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
7339c1045ffSDmitry Chagin     siginfo_t *si, int sig)
7347ac9766dSDmitry Chagin {
7357ac9766dSDmitry Chagin 
7369c1045ffSDmitry Chagin 	switch (lsi->lsi_code) {
7379c1045ffSDmitry Chagin 	case LINUX_SI_TKILL:
7389c1045ffSDmitry Chagin 		if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
7399c1045ffSDmitry Chagin 			linux_msg(td, "SI_TKILL forbidden since 2.6.39");
7409c1045ffSDmitry Chagin 			return (EPERM);
7419c1045ffSDmitry Chagin 		}
7429c1045ffSDmitry Chagin 		si->si_code = SI_LWP;
7439c1045ffSDmitry Chagin 	case LINUX_SI_QUEUE:
7449c1045ffSDmitry Chagin 		si->si_code = SI_QUEUE;
7459c1045ffSDmitry Chagin 		break;
7469c1045ffSDmitry Chagin 	case LINUX_SI_TIMER:
7479c1045ffSDmitry Chagin 		si->si_code = SI_TIMER;
7489c1045ffSDmitry Chagin 		break;
7499c1045ffSDmitry Chagin 	case LINUX_SI_MESGQ:
7509c1045ffSDmitry Chagin 		si->si_code = SI_MESGQ;
7519c1045ffSDmitry Chagin 		break;
7529c1045ffSDmitry Chagin 	case LINUX_SI_ASYNCIO:
7539c1045ffSDmitry Chagin 		si->si_code = SI_ASYNCIO;
7549c1045ffSDmitry Chagin 		break;
7559c1045ffSDmitry Chagin 	default:
7569c1045ffSDmitry Chagin 		si->si_code = lsi->lsi_code;
7579c1045ffSDmitry Chagin 		break;
7589c1045ffSDmitry Chagin 	}
7599c1045ffSDmitry Chagin 
7609c1045ffSDmitry Chagin 	si->si_signo = sig;
7619c1045ffSDmitry Chagin 	si->si_pid = td->td_proc->p_pid;
7629c1045ffSDmitry Chagin 	si->si_uid = td->td_ucred->cr_ruid;
7639c1045ffSDmitry Chagin 	si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
7649c1045ffSDmitry Chagin 	return (0);
7657ac9766dSDmitry Chagin }
7667ac9766dSDmitry Chagin 
7677ac9766dSDmitry Chagin int
7687ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7697ac9766dSDmitry Chagin {
7707ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7717ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7727ac9766dSDmitry Chagin 	int error;
7737ac9766dSDmitry Chagin 	int sig;
7747ac9766dSDmitry Chagin 
7757ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7767ac9766dSDmitry Chagin 		return (EINVAL);
7777ac9766dSDmitry Chagin 
7787ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7797ac9766dSDmitry Chagin 	if (error != 0)
7807ac9766dSDmitry Chagin 		return (error);
7817ac9766dSDmitry Chagin 
7827ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7839c1045ffSDmitry Chagin 		/* SI_USER, SI_KERNEL */
7847ac9766dSDmitry Chagin 		return (EPERM);
7857ac9766dSDmitry Chagin 
7864ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7879c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7889c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7899c1045ffSDmitry Chagin 	if (error != 0)
7909c1045ffSDmitry Chagin 		return (error);
7917ac9766dSDmitry Chagin 
7926201a50dSDmitry Chagin 	return (linux_pksignal(td, args->pid, sig, &ksi));
7937ac9766dSDmitry Chagin }
794486a06bdSDmitry Chagin 
795486a06bdSDmitry Chagin int
796486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
797486a06bdSDmitry Chagin {
798486a06bdSDmitry Chagin 	l_siginfo_t linfo;
799486a06bdSDmitry Chagin 	ksiginfo_t ksi;
800486a06bdSDmitry Chagin 	int error;
801486a06bdSDmitry Chagin 	int sig;
802486a06bdSDmitry Chagin 
803486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
804486a06bdSDmitry Chagin 		return (EINVAL);
805486a06bdSDmitry Chagin 
806486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
807486a06bdSDmitry Chagin 	if (error != 0)
808486a06bdSDmitry Chagin 		return (error);
809486a06bdSDmitry Chagin 
810486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
811486a06bdSDmitry Chagin 		return (EPERM);
812486a06bdSDmitry Chagin 
8139c1045ffSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
8149c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
8159c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
8169c1045ffSDmitry Chagin 	if (error != 0)
8179c1045ffSDmitry Chagin 		return (error);
8189c1045ffSDmitry Chagin 
8196201a50dSDmitry Chagin 	return (linux_tdksignal(td, args->tid, args->tgid, sig, &ksi));
820486a06bdSDmitry Chagin }
82172f7ddb5SEdward Tomasz Napierala 
82272f7ddb5SEdward Tomasz Napierala int
82372f7ddb5SEdward Tomasz Napierala linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
82472f7ddb5SEdward Tomasz Napierala {
82572f7ddb5SEdward Tomasz Napierala 	sigset_t sigmask;
82672f7ddb5SEdward Tomasz Napierala 	int error;
82772f7ddb5SEdward Tomasz Napierala 
8283923e632SDmitry Chagin 	error = linux_copyin_sigset(uap->newset, uap->sigsetsize,
8293923e632SDmitry Chagin 	    &sigmask, NULL);
83072f7ddb5SEdward Tomasz Napierala 	if (error != 0)
83172f7ddb5SEdward Tomasz Napierala 		return (error);
83272f7ddb5SEdward Tomasz Napierala 
83372f7ddb5SEdward Tomasz Napierala 	return (kern_sigsuspend(td, sigmask));
83472f7ddb5SEdward Tomasz Napierala }
8356201a50dSDmitry Chagin 
8366201a50dSDmitry Chagin static int
8376201a50dSDmitry Chagin linux_tdksignal(struct thread *td, lwpid_t tid, int tgid, int sig,
8386201a50dSDmitry Chagin     ksiginfo_t *ksi)
8396201a50dSDmitry Chagin {
8406201a50dSDmitry Chagin 	struct thread *tdt;
8416201a50dSDmitry Chagin 	struct proc *p;
8426201a50dSDmitry Chagin 	int error;
8436201a50dSDmitry Chagin 
8446201a50dSDmitry Chagin 	tdt = linux_tdfind(td, tid, tgid);
8456201a50dSDmitry Chagin 	if (tdt == NULL)
8466201a50dSDmitry Chagin 		return (ESRCH);
8476201a50dSDmitry Chagin 
8486201a50dSDmitry Chagin 	p = tdt->td_proc;
8496201a50dSDmitry Chagin 	AUDIT_ARG_SIGNUM(sig);
8506201a50dSDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
8516201a50dSDmitry Chagin 	AUDIT_ARG_PROCESS(p);
8526201a50dSDmitry Chagin 
8536201a50dSDmitry Chagin 	error = p_cansignal(td, p, sig);
8546201a50dSDmitry Chagin 	if (error != 0 || sig == 0)
8556201a50dSDmitry Chagin 		goto out;
8566201a50dSDmitry Chagin 
8576201a50dSDmitry Chagin 	tdksignal(tdt, sig, ksi);
8586201a50dSDmitry Chagin 
8596201a50dSDmitry Chagin out:
8606201a50dSDmitry Chagin 	PROC_UNLOCK(p);
8616201a50dSDmitry Chagin 	return (error);
8626201a50dSDmitry Chagin }
8636201a50dSDmitry Chagin 
8646201a50dSDmitry Chagin static int
8656201a50dSDmitry Chagin linux_tdsignal(struct thread *td, lwpid_t tid, int tgid, int sig)
8666201a50dSDmitry Chagin {
8676201a50dSDmitry Chagin 	ksiginfo_t ksi;
8686201a50dSDmitry Chagin 
8696201a50dSDmitry Chagin 	ksiginfo_init(&ksi);
8706201a50dSDmitry Chagin 	ksi.ksi_signo = sig;
8716201a50dSDmitry Chagin 	ksi.ksi_code = SI_LWP;
8726201a50dSDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
8736201a50dSDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
8746201a50dSDmitry Chagin 	return (linux_tdksignal(td, tid, tgid, sig, &ksi));
8756201a50dSDmitry Chagin }
8766201a50dSDmitry Chagin 
8776201a50dSDmitry Chagin static int
8786201a50dSDmitry Chagin linux_pksignal(struct thread *td, int pid, int sig, ksiginfo_t *ksi)
8796201a50dSDmitry Chagin {
8806201a50dSDmitry Chagin 	struct thread *tdt;
8816201a50dSDmitry Chagin 	struct proc *p;
8826201a50dSDmitry Chagin 	int error;
8836201a50dSDmitry Chagin 
8846201a50dSDmitry Chagin 	tdt = linux_tdfind(td, pid, -1);
8856201a50dSDmitry Chagin 	if (tdt == NULL)
8866201a50dSDmitry Chagin 		return (ESRCH);
8876201a50dSDmitry Chagin 
8886201a50dSDmitry Chagin 	p = tdt->td_proc;
8896201a50dSDmitry Chagin 	AUDIT_ARG_SIGNUM(sig);
8906201a50dSDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
8916201a50dSDmitry Chagin 	AUDIT_ARG_PROCESS(p);
8926201a50dSDmitry Chagin 
8936201a50dSDmitry Chagin 	error = p_cansignal(td, p, sig);
8946201a50dSDmitry Chagin 	if (error != 0 || sig == 0)
8956201a50dSDmitry Chagin 		goto out;
8966201a50dSDmitry Chagin 
8976201a50dSDmitry Chagin 	pksignal(p, sig, ksi);
8986201a50dSDmitry Chagin 
8996201a50dSDmitry Chagin out:
9006201a50dSDmitry Chagin 	PROC_UNLOCK(p);
9016201a50dSDmitry Chagin 	return (error);
9026201a50dSDmitry Chagin }
9036201a50dSDmitry Chagin 
9046201a50dSDmitry Chagin static int
9056201a50dSDmitry Chagin linux_psignal(struct thread *td, int pid, int sig)
9066201a50dSDmitry Chagin {
9076201a50dSDmitry Chagin 	ksiginfo_t ksi;
9086201a50dSDmitry Chagin 
9096201a50dSDmitry Chagin 	ksiginfo_init(&ksi);
9106201a50dSDmitry Chagin 	ksi.ksi_signo = sig;
9116201a50dSDmitry Chagin 	ksi.ksi_code = SI_LWP;
9126201a50dSDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
9136201a50dSDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
9146201a50dSDmitry Chagin 	return (linux_pksignal(td, pid, sig, &ksi));
9156201a50dSDmitry Chagin }
9163923e632SDmitry Chagin 
9173923e632SDmitry Chagin int
9183923e632SDmitry Chagin linux_copyin_sigset(l_sigset_t *lset, l_size_t sigsetsize, sigset_t *set,
9193923e632SDmitry Chagin     sigset_t **pset)
9203923e632SDmitry Chagin {
9213923e632SDmitry Chagin 	l_sigset_t lmask;
9223923e632SDmitry Chagin 	int error;
9233923e632SDmitry Chagin 
9243923e632SDmitry Chagin 	if (sigsetsize != sizeof(l_sigset_t))
9253923e632SDmitry Chagin 		return (EINVAL);
9263923e632SDmitry Chagin 	if (lset != NULL) {
927*2722e515SDmitry Chagin 		error = copyin(lset, &lmask, sizeof(lmask));
9283923e632SDmitry Chagin 		if (error != 0)
9293923e632SDmitry Chagin 			return (error);
9303923e632SDmitry Chagin 		linux_to_bsd_sigset(&lmask, set);
9313923e632SDmitry Chagin 		if (pset != NULL)
9323923e632SDmitry Chagin 			*pset = set;
9333923e632SDmitry Chagin 	} else if (pset != NULL)
9343923e632SDmitry Chagin 		*pset = NULL;
9353923e632SDmitry Chagin 	return (0);
9363923e632SDmitry Chagin }
937