xref: /freebsd/sys/compat/linux/linux_signal.c (revision 3923e632094a7e4cc66cd8e68964b9cb495119e2)
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);
68fe4ed1e7SDmitry Chagin static void	sicode_to_lsicode(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);
18406ebbe77SMarcel Moolenaar 	if (error)
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) {
20430c6d982SEdward Tomasz Napierala 		error = copyin(uap->uss, &lss, sizeof(l_stack_t));
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);
21830c6d982SEdward Tomasz Napierala 		error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
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) {
2525002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
25306ebbe77SMarcel Moolenaar 		if (error)
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 
261956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2625002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
26306ebbe77SMarcel Moolenaar 	}
26406ebbe77SMarcel Moolenaar 
265956d3333SMarcel Moolenaar 	return (error);
26606ebbe77SMarcel Moolenaar }
26706ebbe77SMarcel Moolenaar 
26806ebbe77SMarcel Moolenaar static int
269b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2705002a60fSMarcel Moolenaar 		     l_sigset_t *old)
27106ebbe77SMarcel Moolenaar {
272fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
273fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
274216af822SJohn Baldwin 	int error;
27506ebbe77SMarcel Moolenaar 
276b40ce416SJulian Elischer 	td->td_retval[0] = 0;
277d66a5066SPeter Wemm 
27819dde5cdSJohn Baldwin 	switch (how) {
27919dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
28019dde5cdSJohn Baldwin 		how = SIG_BLOCK;
28119dde5cdSJohn Baldwin 		break;
28219dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
28319dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
28419dde5cdSJohn Baldwin 		break;
28519dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
28619dde5cdSJohn Baldwin 		how = SIG_SETMASK;
28719dde5cdSJohn Baldwin 		break;
28819dde5cdSJohn Baldwin 	default:
28919dde5cdSJohn Baldwin 		return (EINVAL);
29019dde5cdSJohn Baldwin 	}
29106ebbe77SMarcel Moolenaar 	if (new != NULL) {
292fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
293fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
294fe8cdcaeSJohn Baldwin 	} else
295fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
29619dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2972f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
298fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
29906ebbe77SMarcel Moolenaar 
300956d3333SMarcel Moolenaar 	return (error);
30106ebbe77SMarcel Moolenaar }
30206ebbe77SMarcel Moolenaar 
3037f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
30406ebbe77SMarcel Moolenaar int
305b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
30606ebbe77SMarcel Moolenaar {
3075002a60fSMarcel Moolenaar 	l_osigset_t mask;
3085002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
30906ebbe77SMarcel Moolenaar 	int error;
31006ebbe77SMarcel Moolenaar 
31106ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3125002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
31306ebbe77SMarcel Moolenaar 		if (error)
314956d3333SMarcel Moolenaar 			return (error);
315956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
3164ab7403bSDmitry Chagin 		set.__mask = mask;
31706ebbe77SMarcel Moolenaar 	}
31806ebbe77SMarcel Moolenaar 
319b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
320956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
321956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
32206ebbe77SMarcel Moolenaar 
323956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3244ab7403bSDmitry Chagin 		mask = oset.__mask;
3255002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
32606ebbe77SMarcel Moolenaar 	}
32706ebbe77SMarcel Moolenaar 
328956d3333SMarcel Moolenaar 	return (error);
32906ebbe77SMarcel Moolenaar }
3307f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
33106ebbe77SMarcel Moolenaar 
33206ebbe77SMarcel Moolenaar int
333b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
33406ebbe77SMarcel Moolenaar {
3355002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
33606ebbe77SMarcel Moolenaar 	int error;
33706ebbe77SMarcel Moolenaar 
3385002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
339340f4a8dSEd Maste 		return (EINVAL);
34006ebbe77SMarcel Moolenaar 
34106ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3425002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
34306ebbe77SMarcel Moolenaar 		if (error)
344956d3333SMarcel Moolenaar 			return (error);
34506ebbe77SMarcel Moolenaar 	}
34606ebbe77SMarcel Moolenaar 
347b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
348956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
349956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
35006ebbe77SMarcel Moolenaar 
351956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3525002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
35306ebbe77SMarcel Moolenaar 	}
35406ebbe77SMarcel Moolenaar 
355956d3333SMarcel Moolenaar 	return (error);
356c21dee17SSøren Schmidt }
357c21dee17SSøren Schmidt 
3587f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
359c21dee17SSøren Schmidt int
360b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
361c21dee17SSøren Schmidt {
362b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3635002a60fSMarcel Moolenaar 	l_sigset_t mask;
364956d3333SMarcel Moolenaar 
365216af822SJohn Baldwin 	PROC_LOCK(p);
3664093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
367216af822SJohn Baldwin 	PROC_UNLOCK(p);
3684ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
369956d3333SMarcel Moolenaar 	return (0);
370c21dee17SSøren Schmidt }
371c21dee17SSøren Schmidt 
372c21dee17SSøren Schmidt int
373b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
374c21dee17SSøren Schmidt {
375b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3765002a60fSMarcel Moolenaar 	l_sigset_t lset;
377956d3333SMarcel Moolenaar 	sigset_t bset;
378c21dee17SSøren Schmidt 
379216af822SJohn Baldwin 	PROC_LOCK(p);
3804093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3814ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
382956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3834ab7403bSDmitry Chagin 	lset.__mask = args->mask;
384956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3854093529dSJeff Roberson 	td->td_sigmask = bset;
3864093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3874093529dSJeff Roberson 	signotify(td);
388216af822SJohn Baldwin 	PROC_UNLOCK(p);
389956d3333SMarcel Moolenaar 	return (0);
390c21dee17SSøren Schmidt }
391c21dee17SSøren Schmidt 
392c21dee17SSøren Schmidt int
393b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
394c21dee17SSøren Schmidt {
395b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
396956d3333SMarcel Moolenaar 	sigset_t bset;
3975002a60fSMarcel Moolenaar 	l_sigset_t lset;
3985002a60fSMarcel Moolenaar 	l_osigset_t mask;
399c21dee17SSøren Schmidt 
400216af822SJohn Baldwin 	PROC_LOCK(p);
4011d9c5696SJuli Mallett 	bset = p->p_siglist;
4024093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
4034093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
404216af822SJohn Baldwin 	PROC_UNLOCK(p);
4059d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
4064ab7403bSDmitry Chagin 	mask = lset.__mask;
407956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
408c21dee17SSøren Schmidt }
4097f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
41017138b61SAlexander Leidinger 
41117138b61SAlexander Leidinger /*
41217138b61SAlexander Leidinger  * MPSAFE
41317138b61SAlexander Leidinger  */
41417138b61SAlexander Leidinger int
41517138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
41617138b61SAlexander Leidinger {
41717138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
41817138b61SAlexander Leidinger 	sigset_t bset;
41917138b61SAlexander Leidinger 	l_sigset_t lset;
42017138b61SAlexander Leidinger 
42117138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
422340f4a8dSEd Maste 		return (EINVAL);
42317138b61SAlexander Leidinger 		/* NOT REACHED */
42417138b61SAlexander Leidinger 
42517138b61SAlexander Leidinger 	PROC_LOCK(p);
42617138b61SAlexander Leidinger 	bset = p->p_siglist;
42717138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
42817138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
42917138b61SAlexander Leidinger 	PROC_UNLOCK(p);
43017138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
43117138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
43217138b61SAlexander Leidinger }
433c21dee17SSøren Schmidt 
434c9447c75SAlexander Leidinger int
435c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
436c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
437c9447c75SAlexander Leidinger {
438c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
4390f8dab45SDmitry Chagin 	struct l_timespec lts;
440db4a1f33SDmitry Chagin 	int error;
441c9447c75SAlexander Leidinger 
442c9447c75SAlexander Leidinger 	if (args->timeout) {
4430f8dab45SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
444c9447c75SAlexander Leidinger 			return (error);
4450f8dab45SDmitry Chagin 		error = linux_to_native_timespec(&ts, &lts);
4460f8dab45SDmitry Chagin 		if (error != 0)
4470f8dab45SDmitry Chagin 			return (error);
448c9447c75SAlexander Leidinger 		tsa = &ts;
4490f8dab45SDmitry Chagin 	} else
4500f8dab45SDmitry Chagin 		tsa = NULL;
4510f8dab45SDmitry Chagin 
452db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
453db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
454db4a1f33SDmitry Chagin }
455db4a1f33SDmitry Chagin 
456db4a1f33SDmitry Chagin static int
457db4a1f33SDmitry Chagin linux_common_rt_sigtimedwait(struct thread *td, l_sigset_t *mask,
458db4a1f33SDmitry Chagin     struct timespec *tsa, l_siginfo_t *ptr, l_size_t sigsetsize)
459db4a1f33SDmitry Chagin {
460db4a1f33SDmitry Chagin 	int error, sig;
461db4a1f33SDmitry Chagin 	sigset_t bset;
462db4a1f33SDmitry Chagin 	l_siginfo_t lsi;
463db4a1f33SDmitry Chagin 	ksiginfo_t ksi;
464db4a1f33SDmitry Chagin 
465*3923e632SDmitry Chagin 	error = linux_copyin_sigset(mask, sigsetsize, &bset, NULL);
466*3923e632SDmitry Chagin 	if (error != 0)
467db4a1f33SDmitry Chagin 		return (error);
468db4a1f33SDmitry Chagin 
469db4a1f33SDmitry Chagin 	ksiginfo_init(&ksi);
470f4e80108SDmitry Chagin 	error = kern_sigtimedwait(td, bset, &ksi, tsa);
471c9447c75SAlexander Leidinger 	if (error)
472c9447c75SAlexander Leidinger 		return (error);
473c9447c75SAlexander Leidinger 
474f4e80108SDmitry Chagin 	sig = bsd_to_linux_signal(ksi.ksi_signo);
475f3481dd9SDmitry Chagin 
476db4a1f33SDmitry Chagin 	if (ptr) {
477f4e80108SDmitry Chagin 		memset(&lsi, 0, sizeof(lsi));
478f4e80108SDmitry Chagin 		siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
479db4a1f33SDmitry Chagin 		error = copyout(&lsi, ptr, sizeof(lsi));
480c9447c75SAlexander Leidinger 	}
481f3481dd9SDmitry Chagin 	if (error == 0)
482f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
483c9447c75SAlexander Leidinger 
484c9447c75SAlexander Leidinger 	return (error);
485c9447c75SAlexander Leidinger }
486c9447c75SAlexander Leidinger 
487db4a1f33SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
488db4a1f33SDmitry Chagin int
489db4a1f33SDmitry Chagin linux_rt_sigtimedwait_time64(struct thread *td,
490db4a1f33SDmitry Chagin 	struct linux_rt_sigtimedwait_time64_args *args)
491db4a1f33SDmitry Chagin {
492db4a1f33SDmitry Chagin 	struct timespec ts, *tsa;
493db4a1f33SDmitry Chagin 	struct l_timespec64 lts;
494db4a1f33SDmitry Chagin 	int error;
495db4a1f33SDmitry Chagin 
496db4a1f33SDmitry Chagin 	if (args->timeout) {
497db4a1f33SDmitry Chagin 		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
498db4a1f33SDmitry Chagin 			return (error);
499db4a1f33SDmitry Chagin 		error = linux_to_native_timespec64(&ts, &lts);
500db4a1f33SDmitry Chagin 		if (error != 0)
501db4a1f33SDmitry Chagin 			return (error);
502db4a1f33SDmitry Chagin 		tsa = &ts;
503db4a1f33SDmitry Chagin 	} else
504db4a1f33SDmitry Chagin 		tsa = NULL;
505db4a1f33SDmitry Chagin 
506db4a1f33SDmitry Chagin 	return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
507db4a1f33SDmitry Chagin 	    args->ptr, args->sigsetsize));
508db4a1f33SDmitry Chagin }
509db4a1f33SDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
510db4a1f33SDmitry Chagin 
511c21dee17SSøren Schmidt int
512b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
513c21dee17SSøren Schmidt {
5146201a50dSDmitry Chagin 	int sig;
515c21dee17SSøren Schmidt 
516956d3333SMarcel Moolenaar 	/*
517956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
518956d3333SMarcel Moolenaar 	 */
51964742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5209a6a64d3SDmitry Chagin 		return (EINVAL);
521956d3333SMarcel Moolenaar 
5224ab7403bSDmitry Chagin 	if (args->signum > 0)
5236201a50dSDmitry Chagin 		sig = linux_to_bsd_signal(args->signum);
524956d3333SMarcel Moolenaar 	else
5256201a50dSDmitry Chagin 		sig = 0;
526956d3333SMarcel Moolenaar 
5276201a50dSDmitry Chagin 	if (args->pid > PID_MAX)
5286201a50dSDmitry Chagin 		return (linux_psignal(td, args->pid, sig));
5296201a50dSDmitry Chagin 	else
5306201a50dSDmitry Chagin 		return (kern_kill(td, args->pid, sig));
531aa8b2011SKonstantin Belousov }
532aa8b2011SKonstantin Belousov 
5339b44bfc5SAlexander Leidinger int
5349b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5359b44bfc5SAlexander Leidinger {
53681338031SDmitry Chagin 	int sig;
5379b44bfc5SAlexander Leidinger 
538aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
539aa8b2011SKonstantin Belousov 		return (EINVAL);
5409b44bfc5SAlexander Leidinger 
54181338031SDmitry Chagin 	/*
54281338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
54381338031SDmitry Chagin 	 */
54481338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
54581338031SDmitry Chagin 		return (EINVAL);
54681338031SDmitry Chagin 
5474ab7403bSDmitry Chagin 	if (args->sig > 0)
5484ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
54981338031SDmitry Chagin 	else
5504ab7403bSDmitry Chagin 		sig = 0;
55181338031SDmitry Chagin 
5526201a50dSDmitry Chagin 	return (linux_tdsignal(td, args->pid, args->tgid, sig));
5539b44bfc5SAlexander Leidinger }
5549b44bfc5SAlexander Leidinger 
55581338031SDmitry Chagin /*
55681338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
55781338031SDmitry Chagin  */
5589b44bfc5SAlexander Leidinger int
5599b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5609b44bfc5SAlexander Leidinger {
56181338031SDmitry Chagin 	int sig;
56281338031SDmitry Chagin 
563aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
564aa8b2011SKonstantin Belousov 		return (EINVAL);
5659b44bfc5SAlexander Leidinger 
56681338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
56781338031SDmitry Chagin 		return (EINVAL);
56881338031SDmitry Chagin 
5694ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
57081338031SDmitry Chagin 
5716201a50dSDmitry Chagin 	return (linux_tdsignal(td, args->tid, -1, sig));
572aa8b2011SKonstantin Belousov }
573aa8b2011SKonstantin Belousov 
574fe4ed1e7SDmitry Chagin static void
575fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
576fe4ed1e7SDmitry Chagin {
577fe4ed1e7SDmitry Chagin 
578fe4ed1e7SDmitry Chagin 	switch (si_code) {
579fe4ed1e7SDmitry Chagin 	case SI_USER:
580fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
581fe4ed1e7SDmitry Chagin 		break;
582fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
583fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
584fe4ed1e7SDmitry Chagin 		break;
585fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
586fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
587fe4ed1e7SDmitry Chagin 		break;
588fe4ed1e7SDmitry Chagin 	case SI_TIMER:
589fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
590fe4ed1e7SDmitry Chagin 		break;
591fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
592fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
593fe4ed1e7SDmitry Chagin 		break;
594fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
595fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
596fe4ed1e7SDmitry Chagin 		break;
597fe4ed1e7SDmitry Chagin 	case SI_LWP:
598fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
599fe4ed1e7SDmitry Chagin 		break;
600fe4ed1e7SDmitry Chagin 	default:
601fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
602fe4ed1e7SDmitry Chagin 		break;
603fe4ed1e7SDmitry Chagin 	}
604fe4ed1e7SDmitry Chagin }
605fe4ed1e7SDmitry Chagin 
606fe4ed1e7SDmitry Chagin void
607fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
608fe4ed1e7SDmitry Chagin {
609fe4ed1e7SDmitry Chagin 
610fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
611fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
612fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
613fe4ed1e7SDmitry Chagin 
614fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
615fe4ed1e7SDmitry Chagin 	case SI_LWP:
616fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
617fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
618fe4ed1e7SDmitry Chagin 		break;
619fe4ed1e7SDmitry Chagin 
620fe4ed1e7SDmitry Chagin 	case SI_TIMER:
621fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
622fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
623fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
624fe4ed1e7SDmitry Chagin 		break;
625fe4ed1e7SDmitry Chagin 
626fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
627fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
628fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
629fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
630fe4ed1e7SDmitry Chagin 		break;
631fe4ed1e7SDmitry Chagin 
632fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
633fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
634fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
635fe4ed1e7SDmitry Chagin 		break;
636fe4ed1e7SDmitry Chagin 
637fe4ed1e7SDmitry Chagin 	default:
638aa8b2011SKonstantin Belousov 		switch (sig) {
639aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
640aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
641fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
642aa8b2011SKonstantin Belousov 			break;
643fe4ed1e7SDmitry Chagin 
644aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
645fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
646fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
647fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
648fe4ed1e7SDmitry Chagin 
649c8c93b15SEdward Tomasz Napierala 			if (si->si_code == CLD_STOPPED || si->si_code == CLD_KILLED)
6504ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
651fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
6524ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
653fe4ed1e7SDmitry Chagin 			else
654fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
655aa8b2011SKonstantin Belousov 			break;
656fe4ed1e7SDmitry Chagin 
657aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
658aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
659aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
660aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
661fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
662aa8b2011SKonstantin Belousov 			break;
663fe4ed1e7SDmitry Chagin 
664aa8b2011SKonstantin Belousov 		default:
665fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
666fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
667fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
668fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
669fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
670fe4ed1e7SDmitry Chagin 			}
671aa8b2011SKonstantin Belousov 			break;
672aa8b2011SKonstantin Belousov 		}
673fe4ed1e7SDmitry Chagin 		break;
67409d6cb0aSDmitry Chagin 	}
6759b44bfc5SAlexander Leidinger }
6767ac9766dSDmitry Chagin 
6779c1045ffSDmitry Chagin int
6789c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
6799c1045ffSDmitry Chagin     siginfo_t *si, int sig)
6807ac9766dSDmitry Chagin {
6817ac9766dSDmitry Chagin 
6829c1045ffSDmitry Chagin 	switch (lsi->lsi_code) {
6839c1045ffSDmitry Chagin 	case LINUX_SI_TKILL:
6849c1045ffSDmitry Chagin 		if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
6859c1045ffSDmitry Chagin 			linux_msg(td, "SI_TKILL forbidden since 2.6.39");
6869c1045ffSDmitry Chagin 			return (EPERM);
6879c1045ffSDmitry Chagin 		}
6889c1045ffSDmitry Chagin 		si->si_code = SI_LWP;
6899c1045ffSDmitry Chagin 	case LINUX_SI_QUEUE:
6909c1045ffSDmitry Chagin 		si->si_code = SI_QUEUE;
6919c1045ffSDmitry Chagin 		break;
6929c1045ffSDmitry Chagin 	case LINUX_SI_TIMER:
6939c1045ffSDmitry Chagin 		si->si_code = SI_TIMER;
6949c1045ffSDmitry Chagin 		break;
6959c1045ffSDmitry Chagin 	case LINUX_SI_MESGQ:
6969c1045ffSDmitry Chagin 		si->si_code = SI_MESGQ;
6979c1045ffSDmitry Chagin 		break;
6989c1045ffSDmitry Chagin 	case LINUX_SI_ASYNCIO:
6999c1045ffSDmitry Chagin 		si->si_code = SI_ASYNCIO;
7009c1045ffSDmitry Chagin 		break;
7019c1045ffSDmitry Chagin 	default:
7029c1045ffSDmitry Chagin 		si->si_code = lsi->lsi_code;
7039c1045ffSDmitry Chagin 		break;
7049c1045ffSDmitry Chagin 	}
7059c1045ffSDmitry Chagin 
7069c1045ffSDmitry Chagin 	si->si_signo = sig;
7079c1045ffSDmitry Chagin 	si->si_pid = td->td_proc->p_pid;
7089c1045ffSDmitry Chagin 	si->si_uid = td->td_ucred->cr_ruid;
7099c1045ffSDmitry Chagin 	si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
7109c1045ffSDmitry Chagin 	return (0);
7117ac9766dSDmitry Chagin }
7127ac9766dSDmitry Chagin 
7137ac9766dSDmitry Chagin int
7147ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7157ac9766dSDmitry Chagin {
7167ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7177ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7187ac9766dSDmitry Chagin 	int error;
7197ac9766dSDmitry Chagin 	int sig;
7207ac9766dSDmitry Chagin 
7217ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7227ac9766dSDmitry Chagin 		return (EINVAL);
7237ac9766dSDmitry Chagin 
7247ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7257ac9766dSDmitry Chagin 	if (error != 0)
7267ac9766dSDmitry Chagin 		return (error);
7277ac9766dSDmitry Chagin 
7287ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7299c1045ffSDmitry Chagin 		/* SI_USER, SI_KERNEL */
7307ac9766dSDmitry Chagin 		return (EPERM);
7317ac9766dSDmitry Chagin 
7324ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7339c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7349c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7359c1045ffSDmitry Chagin 	if (error != 0)
7369c1045ffSDmitry Chagin 		return (error);
7377ac9766dSDmitry Chagin 
7386201a50dSDmitry Chagin 	return (linux_pksignal(td, args->pid, sig, &ksi));
7397ac9766dSDmitry Chagin }
740486a06bdSDmitry Chagin 
741486a06bdSDmitry Chagin int
742486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
743486a06bdSDmitry Chagin {
744486a06bdSDmitry Chagin 	l_siginfo_t linfo;
745486a06bdSDmitry Chagin 	ksiginfo_t ksi;
746486a06bdSDmitry Chagin 	int error;
747486a06bdSDmitry Chagin 	int sig;
748486a06bdSDmitry Chagin 
749486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
750486a06bdSDmitry Chagin 		return (EINVAL);
751486a06bdSDmitry Chagin 
752486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
753486a06bdSDmitry Chagin 	if (error != 0)
754486a06bdSDmitry Chagin 		return (error);
755486a06bdSDmitry Chagin 
756486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
757486a06bdSDmitry Chagin 		return (EPERM);
758486a06bdSDmitry Chagin 
7599c1045ffSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7609c1045ffSDmitry Chagin 	ksiginfo_init(&ksi);
7619c1045ffSDmitry Chagin 	error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
7629c1045ffSDmitry Chagin 	if (error != 0)
7639c1045ffSDmitry Chagin 		return (error);
7649c1045ffSDmitry Chagin 
7656201a50dSDmitry Chagin 	return (linux_tdksignal(td, args->tid, args->tgid, sig, &ksi));
766486a06bdSDmitry Chagin }
76772f7ddb5SEdward Tomasz Napierala 
76872f7ddb5SEdward Tomasz Napierala int
76972f7ddb5SEdward Tomasz Napierala linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
77072f7ddb5SEdward Tomasz Napierala {
77172f7ddb5SEdward Tomasz Napierala 	sigset_t sigmask;
77272f7ddb5SEdward Tomasz Napierala 	int error;
77372f7ddb5SEdward Tomasz Napierala 
774*3923e632SDmitry Chagin 	error = linux_copyin_sigset(uap->newset, uap->sigsetsize,
775*3923e632SDmitry Chagin 	    &sigmask, NULL);
77672f7ddb5SEdward Tomasz Napierala 	if (error != 0)
77772f7ddb5SEdward Tomasz Napierala 		return (error);
77872f7ddb5SEdward Tomasz Napierala 
77972f7ddb5SEdward Tomasz Napierala 	return (kern_sigsuspend(td, sigmask));
78072f7ddb5SEdward Tomasz Napierala }
7816201a50dSDmitry Chagin 
7826201a50dSDmitry Chagin static int
7836201a50dSDmitry Chagin linux_tdksignal(struct thread *td, lwpid_t tid, int tgid, int sig,
7846201a50dSDmitry Chagin     ksiginfo_t *ksi)
7856201a50dSDmitry Chagin {
7866201a50dSDmitry Chagin 	struct thread *tdt;
7876201a50dSDmitry Chagin 	struct proc *p;
7886201a50dSDmitry Chagin 	int error;
7896201a50dSDmitry Chagin 
7906201a50dSDmitry Chagin 	tdt = linux_tdfind(td, tid, tgid);
7916201a50dSDmitry Chagin 	if (tdt == NULL)
7926201a50dSDmitry Chagin 		return (ESRCH);
7936201a50dSDmitry Chagin 
7946201a50dSDmitry Chagin 	p = tdt->td_proc;
7956201a50dSDmitry Chagin 	AUDIT_ARG_SIGNUM(sig);
7966201a50dSDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
7976201a50dSDmitry Chagin 	AUDIT_ARG_PROCESS(p);
7986201a50dSDmitry Chagin 
7996201a50dSDmitry Chagin 	error = p_cansignal(td, p, sig);
8006201a50dSDmitry Chagin 	if (error != 0 || sig == 0)
8016201a50dSDmitry Chagin 		goto out;
8026201a50dSDmitry Chagin 
8036201a50dSDmitry Chagin 	tdksignal(tdt, sig, ksi);
8046201a50dSDmitry Chagin 
8056201a50dSDmitry Chagin out:
8066201a50dSDmitry Chagin 	PROC_UNLOCK(p);
8076201a50dSDmitry Chagin 	return (error);
8086201a50dSDmitry Chagin }
8096201a50dSDmitry Chagin 
8106201a50dSDmitry Chagin static int
8116201a50dSDmitry Chagin linux_tdsignal(struct thread *td, lwpid_t tid, int tgid, int sig)
8126201a50dSDmitry Chagin {
8136201a50dSDmitry Chagin 	ksiginfo_t ksi;
8146201a50dSDmitry Chagin 
8156201a50dSDmitry Chagin 	ksiginfo_init(&ksi);
8166201a50dSDmitry Chagin 	ksi.ksi_signo = sig;
8176201a50dSDmitry Chagin 	ksi.ksi_code = SI_LWP;
8186201a50dSDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
8196201a50dSDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
8206201a50dSDmitry Chagin 	return (linux_tdksignal(td, tid, tgid, sig, &ksi));
8216201a50dSDmitry Chagin }
8226201a50dSDmitry Chagin 
8236201a50dSDmitry Chagin static int
8246201a50dSDmitry Chagin linux_pksignal(struct thread *td, int pid, int sig, ksiginfo_t *ksi)
8256201a50dSDmitry Chagin {
8266201a50dSDmitry Chagin 	struct thread *tdt;
8276201a50dSDmitry Chagin 	struct proc *p;
8286201a50dSDmitry Chagin 	int error;
8296201a50dSDmitry Chagin 
8306201a50dSDmitry Chagin 	tdt = linux_tdfind(td, pid, -1);
8316201a50dSDmitry Chagin 	if (tdt == NULL)
8326201a50dSDmitry Chagin 		return (ESRCH);
8336201a50dSDmitry Chagin 
8346201a50dSDmitry Chagin 	p = tdt->td_proc;
8356201a50dSDmitry Chagin 	AUDIT_ARG_SIGNUM(sig);
8366201a50dSDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
8376201a50dSDmitry Chagin 	AUDIT_ARG_PROCESS(p);
8386201a50dSDmitry Chagin 
8396201a50dSDmitry Chagin 	error = p_cansignal(td, p, sig);
8406201a50dSDmitry Chagin 	if (error != 0 || sig == 0)
8416201a50dSDmitry Chagin 		goto out;
8426201a50dSDmitry Chagin 
8436201a50dSDmitry Chagin 	pksignal(p, sig, ksi);
8446201a50dSDmitry Chagin 
8456201a50dSDmitry Chagin out:
8466201a50dSDmitry Chagin 	PROC_UNLOCK(p);
8476201a50dSDmitry Chagin 	return (error);
8486201a50dSDmitry Chagin }
8496201a50dSDmitry Chagin 
8506201a50dSDmitry Chagin static int
8516201a50dSDmitry Chagin linux_psignal(struct thread *td, int pid, int sig)
8526201a50dSDmitry Chagin {
8536201a50dSDmitry Chagin 	ksiginfo_t ksi;
8546201a50dSDmitry Chagin 
8556201a50dSDmitry Chagin 	ksiginfo_init(&ksi);
8566201a50dSDmitry Chagin 	ksi.ksi_signo = sig;
8576201a50dSDmitry Chagin 	ksi.ksi_code = SI_LWP;
8586201a50dSDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
8596201a50dSDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
8606201a50dSDmitry Chagin 	return (linux_pksignal(td, pid, sig, &ksi));
8616201a50dSDmitry Chagin }
862*3923e632SDmitry Chagin 
863*3923e632SDmitry Chagin int
864*3923e632SDmitry Chagin linux_copyin_sigset(l_sigset_t *lset, l_size_t sigsetsize, sigset_t *set,
865*3923e632SDmitry Chagin     sigset_t **pset)
866*3923e632SDmitry Chagin {
867*3923e632SDmitry Chagin 	l_sigset_t lmask;
868*3923e632SDmitry Chagin 	int error;
869*3923e632SDmitry Chagin 
870*3923e632SDmitry Chagin 	if (sigsetsize != sizeof(l_sigset_t))
871*3923e632SDmitry Chagin 		return (EINVAL);
872*3923e632SDmitry Chagin 	if (lset != NULL) {
873*3923e632SDmitry Chagin 		error = copyin(lset, &lmask, sizeof(l_sigset_t));
874*3923e632SDmitry Chagin 		if (error != 0)
875*3923e632SDmitry Chagin 			return (error);
876*3923e632SDmitry Chagin 		linux_to_bsd_sigset(&lmask, set);
877*3923e632SDmitry Chagin 		if (pset != NULL)
878*3923e632SDmitry Chagin 			*pset = set;
879*3923e632SDmitry Chagin 	} else if (pset != NULL)
880*3923e632SDmitry Chagin 		*pset = NULL;
881*3923e632SDmitry Chagin 	return (0);
882*3923e632SDmitry Chagin }
883