xref: /freebsd/sys/compat/linux/linux_signal.c (revision 7f2d13d60721803155950276e0282fcd1e6bacc3)
1c21dee17SSøren Schmidt /*-
2*7f2d13d6SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*7f2d13d6SPedro 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
11c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer
12c21dee17SSøren Schmidt  *    in this position and unchanged.
13c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
14c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
15c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
16c21dee17SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
1721dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
18c21dee17SSøren Schmidt  *
19c21dee17SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20c21dee17SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21c21dee17SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22c21dee17SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23c21dee17SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24c21dee17SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25c21dee17SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26c21dee17SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27c21dee17SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28c21dee17SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29c21dee17SSøren Schmidt  */
30c21dee17SSøren Schmidt 
3116dbc7f2SDavid E. O'Brien #include <sys/cdefs.h>
321e8d246eSNate Lawson __FBSDID("$FreeBSD$");
3316dbc7f2SDavid E. O'Brien 
34c21dee17SSøren Schmidt #include <sys/param.h>
35c21dee17SSøren Schmidt #include <sys/systm.h>
36fb919e4dSMark Murray #include <sys/lock.h>
37fb919e4dSMark Murray #include <sys/mutex.h>
3829ddc19bSAlexander Leidinger #include <sys/sx.h>
39c21dee17SSøren Schmidt #include <sys/proc.h>
40c21dee17SSøren Schmidt #include <sys/signalvar.h>
41206a5d3aSIan Dowse #include <sys/syscallsubr.h>
42fb919e4dSMark Murray #include <sys/sysproto.h>
43c21dee17SSøren Schmidt 
44aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
45aa8b2011SKonstantin Belousov 
46aefce619SRuslan Ermilov #include "opt_compat.h"
47aefce619SRuslan Ermilov 
481997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
494af27623STim J. Robbins #include <machine/../linux32/linux.h>
504af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
511997c537SDavid E. O'Brien #else
521997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
531997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
544af27623STim J. Robbins #endif
55ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
56ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
579b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
5881338031SDmitry Chagin #include <compat/linux/linux_misc.h>
5981338031SDmitry Chagin 
6081338031SDmitry Chagin static int	linux_do_tkill(struct thread *td, struct thread *tdt,
6181338031SDmitry Chagin 		    ksiginfo_t *ksi);
62fe4ed1e7SDmitry Chagin static void	sicode_to_lsicode(int si_code, int *lsi_code);
63fe4ed1e7SDmitry Chagin 
649b44bfc5SAlexander Leidinger 
65a1ebcbfbSPeter Wemm static void
665002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
67d66a5066SPeter Wemm {
68956d3333SMarcel Moolenaar 
69956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
704af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
71d66a5066SPeter Wemm 	bsa->sa_flags = 0;
728f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
73d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
7406ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
7506ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
7606ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
7706ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
788f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
79d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
808f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_RESTART)
81d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
828f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
83d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
848f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOMASK)
85d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
86d66a5066SPeter Wemm }
87d66a5066SPeter Wemm 
88a1ebcbfbSPeter Wemm static void
895002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
90d66a5066SPeter Wemm {
91956d3333SMarcel Moolenaar 
92956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
931997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
944af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
954af27623STim J. Robbins #else
968f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
974af27623STim J. Robbins #endif
984af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
998f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
100d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1018f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
10206ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
10306ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
10406ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
10506ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
106d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1078f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
108d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1098f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
110d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1118f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
112d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1138f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
114d66a5066SPeter Wemm }
115c21dee17SSøren Schmidt 
116ba9ef45bSMarcel Moolenaar int
117b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1185002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
11906ebbe77SMarcel Moolenaar {
120206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
121206a5d3aSIan Dowse 	int error, sig;
12206ebbe77SMarcel Moolenaar 
123687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
124956d3333SMarcel Moolenaar 		return (EINVAL);
12506ebbe77SMarcel Moolenaar 
126206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
127956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
128206a5d3aSIan Dowse 		nsa = &act;
129ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
130206a5d3aSIan Dowse 	} else
13106ebbe77SMarcel Moolenaar 		nsa = NULL;
1324ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(linux_sig);
133956d3333SMarcel Moolenaar 
134206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
13506ebbe77SMarcel Moolenaar 	if (error)
136956d3333SMarcel Moolenaar 		return (error);
13706ebbe77SMarcel Moolenaar 
138ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
139ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
14006ebbe77SMarcel Moolenaar 
141956d3333SMarcel Moolenaar 	return (0);
14206ebbe77SMarcel Moolenaar }
14306ebbe77SMarcel Moolenaar 
1447f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
145c21dee17SSøren Schmidt int
146b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
147d66a5066SPeter Wemm {
1485002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
149d66a5066SPeter Wemm 	int error;
150d66a5066SPeter Wemm 
151d66a5066SPeter Wemm #ifdef DEBUG
15224593369SJonathan Lemon 	if (ldebug(signal))
15324593369SJonathan Lemon 		printf(ARGS(signal, "%d, %p"),
154b61c60d4SDavid E. O'Brien 		    args->sig, (void *)(uintptr_t)args->handler);
155d66a5066SPeter Wemm #endif
156d66a5066SPeter Wemm 
15706ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
15806ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
159956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
160d66a5066SPeter Wemm 
161b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1624af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
163d66a5066SPeter Wemm 
164956d3333SMarcel Moolenaar 	return (error);
165d66a5066SPeter Wemm }
1667f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
167d66a5066SPeter Wemm 
168c21dee17SSøren Schmidt int
169b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
170c21dee17SSøren Schmidt {
1715002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
17206ebbe77SMarcel Moolenaar 	int error;
173c21dee17SSøren Schmidt 
174c21dee17SSøren Schmidt #ifdef DEBUG
17524593369SJonathan Lemon 	if (ldebug(rt_sigaction))
17624593369SJonathan Lemon 		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
17724593369SJonathan Lemon 		    (long)args->sig, (void *)args->act,
1785231fb20SDavid E. O'Brien 		    (void *)args->oact, (long)args->sigsetsize);
179c21dee17SSøren Schmidt #endif
180d66a5066SPeter Wemm 
1815002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
182956d3333SMarcel Moolenaar 		return (EINVAL);
18306ebbe77SMarcel Moolenaar 
184956d3333SMarcel Moolenaar 	if (args->act != NULL) {
1855002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
18606ebbe77SMarcel Moolenaar 		if (error)
187956d3333SMarcel Moolenaar 			return (error);
18806ebbe77SMarcel Moolenaar 	}
18906ebbe77SMarcel Moolenaar 
190b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
19106ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
19206ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
19306ebbe77SMarcel Moolenaar 
194956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
1955002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
19606ebbe77SMarcel Moolenaar 	}
19706ebbe77SMarcel Moolenaar 
198956d3333SMarcel Moolenaar 	return (error);
19906ebbe77SMarcel Moolenaar }
20006ebbe77SMarcel Moolenaar 
20106ebbe77SMarcel Moolenaar static int
202b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2035002a60fSMarcel Moolenaar 		     l_sigset_t *old)
20406ebbe77SMarcel Moolenaar {
205fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
206fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
207216af822SJohn Baldwin 	int error;
20806ebbe77SMarcel Moolenaar 
209b40ce416SJulian Elischer 	td->td_retval[0] = 0;
210d66a5066SPeter Wemm 
21119dde5cdSJohn Baldwin 	switch (how) {
21219dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
21319dde5cdSJohn Baldwin 		how = SIG_BLOCK;
21419dde5cdSJohn Baldwin 		break;
21519dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
21619dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
21719dde5cdSJohn Baldwin 		break;
21819dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
21919dde5cdSJohn Baldwin 		how = SIG_SETMASK;
22019dde5cdSJohn Baldwin 		break;
22119dde5cdSJohn Baldwin 	default:
22219dde5cdSJohn Baldwin 		return (EINVAL);
22319dde5cdSJohn Baldwin 	}
22406ebbe77SMarcel Moolenaar 	if (new != NULL) {
225fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
226fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
227fe8cdcaeSJohn Baldwin 	} else
228fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
22919dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2302f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
231fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
23206ebbe77SMarcel Moolenaar 
233956d3333SMarcel Moolenaar 	return (error);
23406ebbe77SMarcel Moolenaar }
23506ebbe77SMarcel Moolenaar 
2367f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
23706ebbe77SMarcel Moolenaar int
238b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
23906ebbe77SMarcel Moolenaar {
2405002a60fSMarcel Moolenaar 	l_osigset_t mask;
2415002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
24206ebbe77SMarcel Moolenaar 	int error;
24306ebbe77SMarcel Moolenaar 
24406ebbe77SMarcel Moolenaar #ifdef DEBUG
24524593369SJonathan Lemon 	if (ldebug(sigprocmask))
24624593369SJonathan Lemon 		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
24706ebbe77SMarcel Moolenaar #endif
24806ebbe77SMarcel Moolenaar 
24906ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2505002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
25106ebbe77SMarcel Moolenaar 		if (error)
252956d3333SMarcel Moolenaar 			return (error);
253956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
2544ab7403bSDmitry Chagin 		set.__mask = mask;
25506ebbe77SMarcel Moolenaar 	}
25606ebbe77SMarcel Moolenaar 
257b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
258956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
259956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
26006ebbe77SMarcel Moolenaar 
261956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
2624ab7403bSDmitry Chagin 		mask = oset.__mask;
2635002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
26406ebbe77SMarcel Moolenaar 	}
26506ebbe77SMarcel Moolenaar 
266956d3333SMarcel Moolenaar 	return (error);
26706ebbe77SMarcel Moolenaar }
2687f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
26906ebbe77SMarcel Moolenaar 
27006ebbe77SMarcel Moolenaar int
271b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
27206ebbe77SMarcel Moolenaar {
2735002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
27406ebbe77SMarcel Moolenaar 	int error;
27506ebbe77SMarcel Moolenaar 
27606ebbe77SMarcel Moolenaar #ifdef DEBUG
27724593369SJonathan Lemon 	if (ldebug(rt_sigprocmask))
27824593369SJonathan Lemon 		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
27924593369SJonathan Lemon 		    args->how, (void *)args->mask,
2805231fb20SDavid E. O'Brien 		    (void *)args->omask, (long)args->sigsetsize);
28106ebbe77SMarcel Moolenaar #endif
28206ebbe77SMarcel Moolenaar 
2835002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
28406ebbe77SMarcel Moolenaar 		return EINVAL;
28506ebbe77SMarcel Moolenaar 
28606ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2875002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
28806ebbe77SMarcel Moolenaar 		if (error)
289956d3333SMarcel Moolenaar 			return (error);
29006ebbe77SMarcel Moolenaar 	}
29106ebbe77SMarcel Moolenaar 
292b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
293956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
294956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
29506ebbe77SMarcel Moolenaar 
296956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
2975002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
29806ebbe77SMarcel Moolenaar 	}
29906ebbe77SMarcel Moolenaar 
300956d3333SMarcel Moolenaar 	return (error);
301c21dee17SSøren Schmidt }
302c21dee17SSøren Schmidt 
3037f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
304c21dee17SSøren Schmidt int
305b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
306c21dee17SSøren Schmidt {
307b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3085002a60fSMarcel Moolenaar 	l_sigset_t mask;
309956d3333SMarcel Moolenaar 
310c21dee17SSøren Schmidt #ifdef DEBUG
3115002a60fSMarcel Moolenaar 	if (ldebug(sgetmask))
3125002a60fSMarcel Moolenaar 		printf(ARGS(sgetmask, ""));
313c21dee17SSøren Schmidt #endif
314956d3333SMarcel Moolenaar 
315216af822SJohn Baldwin 	PROC_LOCK(p);
3164093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
317216af822SJohn Baldwin 	PROC_UNLOCK(p);
3184ab7403bSDmitry Chagin 	td->td_retval[0] = mask.__mask;
319956d3333SMarcel Moolenaar 	return (0);
320c21dee17SSøren Schmidt }
321c21dee17SSøren Schmidt 
322c21dee17SSøren Schmidt int
323b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
324c21dee17SSøren Schmidt {
325b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3265002a60fSMarcel Moolenaar 	l_sigset_t lset;
327956d3333SMarcel Moolenaar 	sigset_t bset;
328c21dee17SSøren Schmidt 
329c21dee17SSøren Schmidt #ifdef DEBUG
3305002a60fSMarcel Moolenaar 	if (ldebug(ssetmask))
3315002a60fSMarcel Moolenaar 		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
332c21dee17SSøren Schmidt #endif
333d66a5066SPeter Wemm 
334216af822SJohn Baldwin 	PROC_LOCK(p);
3354093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
3364ab7403bSDmitry Chagin 	td->td_retval[0] = lset.__mask;
337956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
3384ab7403bSDmitry Chagin 	lset.__mask = args->mask;
339956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3404093529dSJeff Roberson 	td->td_sigmask = bset;
3414093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3424093529dSJeff Roberson 	signotify(td);
343216af822SJohn Baldwin 	PROC_UNLOCK(p);
344956d3333SMarcel Moolenaar 	return (0);
345c21dee17SSøren Schmidt }
346c21dee17SSøren Schmidt 
347c21dee17SSøren Schmidt int
348b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
349c21dee17SSøren Schmidt {
350b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
351956d3333SMarcel Moolenaar 	sigset_t bset;
3525002a60fSMarcel Moolenaar 	l_sigset_t lset;
3535002a60fSMarcel Moolenaar 	l_osigset_t mask;
354c21dee17SSøren Schmidt 
355c21dee17SSøren Schmidt #ifdef DEBUG
35624593369SJonathan Lemon 	if (ldebug(sigpending))
35724593369SJonathan Lemon 		printf(ARGS(sigpending, "*"));
358c21dee17SSøren Schmidt #endif
359956d3333SMarcel Moolenaar 
360216af822SJohn Baldwin 	PROC_LOCK(p);
3611d9c5696SJuli Mallett 	bset = p->p_siglist;
3624093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3634093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
364216af822SJohn Baldwin 	PROC_UNLOCK(p);
3659d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
3664ab7403bSDmitry Chagin 	mask = lset.__mask;
367956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
368c21dee17SSøren Schmidt }
3697f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
37017138b61SAlexander Leidinger 
37117138b61SAlexander Leidinger /*
37217138b61SAlexander Leidinger  * MPSAFE
37317138b61SAlexander Leidinger  */
37417138b61SAlexander Leidinger int
37517138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
37617138b61SAlexander Leidinger {
37717138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
37817138b61SAlexander Leidinger 	sigset_t bset;
37917138b61SAlexander Leidinger 	l_sigset_t lset;
38017138b61SAlexander Leidinger 
38117138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
38217138b61SAlexander Leidinger 		return EINVAL;
38317138b61SAlexander Leidinger 		/* NOT REACHED */
38417138b61SAlexander Leidinger 
38517138b61SAlexander Leidinger #ifdef DEBUG
38617138b61SAlexander Leidinger 	if (ldebug(rt_sigpending))
38717138b61SAlexander Leidinger 		printf(ARGS(rt_sigpending, "*"));
38817138b61SAlexander Leidinger #endif
38917138b61SAlexander Leidinger 
39017138b61SAlexander Leidinger 	PROC_LOCK(p);
39117138b61SAlexander Leidinger 	bset = p->p_siglist;
39217138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
39317138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
39417138b61SAlexander Leidinger 	PROC_UNLOCK(p);
39517138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
39617138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
39717138b61SAlexander Leidinger }
398c21dee17SSøren Schmidt 
399c9447c75SAlexander Leidinger /*
400c9447c75SAlexander Leidinger  * MPSAFE
401c9447c75SAlexander Leidinger  */
402c9447c75SAlexander Leidinger int
403c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
404c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
405c9447c75SAlexander Leidinger {
406f3481dd9SDmitry Chagin 	int error, sig;
407c9447c75SAlexander Leidinger 	l_timeval ltv;
408c9447c75SAlexander Leidinger 	struct timeval tv;
409c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
410c9447c75SAlexander Leidinger 	l_sigset_t lset;
411c9447c75SAlexander Leidinger 	sigset_t bset;
412c9447c75SAlexander Leidinger 	l_siginfo_t linfo;
413c9447c75SAlexander Leidinger 	ksiginfo_t info;
414c9447c75SAlexander Leidinger 
415c9447c75SAlexander Leidinger #ifdef DEBUG
416c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
417c9447c75SAlexander Leidinger 		printf(ARGS(rt_sigtimedwait, "*"));
418c9447c75SAlexander Leidinger #endif
419c9447c75SAlexander Leidinger 	if (args->sigsetsize != sizeof(l_sigset_t))
420c9447c75SAlexander Leidinger 		return (EINVAL);
421c9447c75SAlexander Leidinger 
422c9447c75SAlexander Leidinger 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
423c9447c75SAlexander Leidinger 		return (error);
424c9447c75SAlexander Leidinger 	linux_to_bsd_sigset(&lset, &bset);
425c9447c75SAlexander Leidinger 
426c9447c75SAlexander Leidinger 	tsa = NULL;
427c9447c75SAlexander Leidinger 	if (args->timeout) {
428c9447c75SAlexander Leidinger 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
429c9447c75SAlexander Leidinger 			return (error);
430c9447c75SAlexander Leidinger #ifdef DEBUG
431c9447c75SAlexander Leidinger 		if (ldebug(rt_sigtimedwait))
4328c50c562SDmitry Chagin 			printf(LMSG("linux_rt_sigtimedwait: "
4334ca75bedSDmitry Chagin 			    "incoming timeout (%jd/%jd)\n"),
4344ca75bedSDmitry Chagin 			    (intmax_t)ltv.tv_sec, (intmax_t)ltv.tv_usec);
435c9447c75SAlexander Leidinger #endif
436c9447c75SAlexander Leidinger 		tv.tv_sec = (long)ltv.tv_sec;
437c9447c75SAlexander Leidinger 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
438c9447c75SAlexander Leidinger 		if (itimerfix(&tv)) {
439c9447c75SAlexander Leidinger 			/*
440c9447c75SAlexander Leidinger 			 * The timeout was invalid. Convert it to something
441c9447c75SAlexander Leidinger 			 * valid that will act as it does under Linux.
442c9447c75SAlexander Leidinger 			 */
443c9447c75SAlexander Leidinger 			tv.tv_sec += tv.tv_usec / 1000000;
444c9447c75SAlexander Leidinger 			tv.tv_usec %= 1000000;
445c9447c75SAlexander Leidinger 			if (tv.tv_usec < 0) {
446c9447c75SAlexander Leidinger 				tv.tv_sec -= 1;
447c9447c75SAlexander Leidinger 				tv.tv_usec += 1000000;
448c9447c75SAlexander Leidinger 			}
449c9447c75SAlexander Leidinger 			if (tv.tv_sec < 0)
450c9447c75SAlexander Leidinger 				timevalclear(&tv);
451c9447c75SAlexander Leidinger #ifdef DEBUG
452c9447c75SAlexander Leidinger 			if (ldebug(rt_sigtimedwait))
4538c50c562SDmitry Chagin 				printf(LMSG("linux_rt_sigtimedwait: "
4548c50c562SDmitry Chagin 				    "converted timeout (%jd/%ld)\n"),
45559038483SXin LI 				    (intmax_t)tv.tv_sec, tv.tv_usec);
456c9447c75SAlexander Leidinger #endif
457c9447c75SAlexander Leidinger 		}
458c9447c75SAlexander Leidinger 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
459c9447c75SAlexander Leidinger 		tsa = &ts;
460c9447c75SAlexander Leidinger 	}
461c9447c75SAlexander Leidinger 	error = kern_sigtimedwait(td, bset, &info, tsa);
462c9447c75SAlexander Leidinger #ifdef DEBUG
463c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
4648c50c562SDmitry Chagin 		printf(LMSG("linux_rt_sigtimedwait: "
4658c50c562SDmitry Chagin 		    "sigtimedwait returning (%d)\n"), error);
466c9447c75SAlexander Leidinger #endif
467c9447c75SAlexander Leidinger 	if (error)
468c9447c75SAlexander Leidinger 		return (error);
469c9447c75SAlexander Leidinger 
4704ab7403bSDmitry Chagin 	sig = bsd_to_linux_signal(info.ksi_signo);
471f3481dd9SDmitry Chagin 
472c9447c75SAlexander Leidinger 	if (args->ptr) {
473c9447c75SAlexander Leidinger 		memset(&linfo, 0, sizeof(linfo));
474f3481dd9SDmitry Chagin 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
475c9447c75SAlexander Leidinger 		error = copyout(&linfo, args->ptr, sizeof(linfo));
476c9447c75SAlexander Leidinger 	}
477f3481dd9SDmitry Chagin 	if (error == 0)
478f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
479c9447c75SAlexander Leidinger 
480c9447c75SAlexander Leidinger 	return (error);
481c9447c75SAlexander Leidinger }
482c9447c75SAlexander Leidinger 
483c21dee17SSøren Schmidt int
484b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
485c21dee17SSøren Schmidt {
486ef04503dSPeter Wemm 	struct kill_args /* {
487c21dee17SSøren Schmidt 	    int pid;
488c21dee17SSøren Schmidt 	    int signum;
489ef04503dSPeter Wemm 	} */ tmp;
490c21dee17SSøren Schmidt 
491c21dee17SSøren Schmidt #ifdef DEBUG
49224593369SJonathan Lemon 	if (ldebug(kill))
49324593369SJonathan Lemon 		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
494c21dee17SSøren Schmidt #endif
495956d3333SMarcel Moolenaar 
496956d3333SMarcel Moolenaar 	/*
497956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
498956d3333SMarcel Moolenaar 	 */
49964742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5009a6a64d3SDmitry Chagin 		return (EINVAL);
501956d3333SMarcel Moolenaar 
5024ab7403bSDmitry Chagin 	if (args->signum > 0)
5034ab7403bSDmitry Chagin 		tmp.signum = linux_to_bsd_signal(args->signum);
504956d3333SMarcel Moolenaar 	else
5054ab7403bSDmitry Chagin 		tmp.signum = 0;
506956d3333SMarcel Moolenaar 
507c21dee17SSøren Schmidt 	tmp.pid = args->pid;
5088451d0ddSKip Macy 	return (sys_kill(td, &tmp));
509c21dee17SSøren Schmidt }
5109b44bfc5SAlexander Leidinger 
511aa8b2011SKonstantin Belousov static int
51281338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
513aa8b2011SKonstantin Belousov {
514aa8b2011SKonstantin Belousov 	struct proc *p;
515aa8b2011SKonstantin Belousov 	int error;
516aa8b2011SKonstantin Belousov 
51781338031SDmitry Chagin 	p = tdt->td_proc;
51881338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
51981338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
52014961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
52181338031SDmitry Chagin 
52281338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
52381338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
524aa8b2011SKonstantin Belousov 		goto out;
525aa8b2011SKonstantin Belousov 
52681338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
527aa8b2011SKonstantin Belousov 
528aa8b2011SKonstantin Belousov out:
529aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
530aa8b2011SKonstantin Belousov 	return (error);
531aa8b2011SKonstantin Belousov }
532aa8b2011SKonstantin Belousov 
5339b44bfc5SAlexander Leidinger int
5349b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5359b44bfc5SAlexander Leidinger {
53681338031SDmitry Chagin 	struct thread *tdt;
53781338031SDmitry Chagin 	ksiginfo_t ksi;
53881338031SDmitry Chagin 	int sig;
5399b44bfc5SAlexander Leidinger 
5409b44bfc5SAlexander Leidinger #ifdef DEBUG
5419b44bfc5SAlexander Leidinger 	if (ldebug(tgkill))
54281338031SDmitry Chagin 		printf(ARGS(tgkill, "%d, %d, %d"),
54381338031SDmitry Chagin 		    args->tgid, args->pid, args->sig);
5449b44bfc5SAlexander Leidinger #endif
54581338031SDmitry Chagin 
546aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
547aa8b2011SKonstantin Belousov 		return (EINVAL);
5489b44bfc5SAlexander Leidinger 
54981338031SDmitry Chagin 	/*
55081338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
55181338031SDmitry Chagin 	 */
55281338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
55381338031SDmitry Chagin 		return (EINVAL);
55481338031SDmitry Chagin 
5554ab7403bSDmitry Chagin 	if (args->sig > 0)
5564ab7403bSDmitry Chagin 		sig = linux_to_bsd_signal(args->sig);
55781338031SDmitry Chagin 	else
5584ab7403bSDmitry Chagin 		sig = 0;
55981338031SDmitry Chagin 
56081338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
56181338031SDmitry Chagin 	if (tdt == NULL)
56281338031SDmitry Chagin 		return (ESRCH);
56381338031SDmitry Chagin 
56481338031SDmitry Chagin 	ksiginfo_init(&ksi);
56581338031SDmitry Chagin 	ksi.ksi_signo = sig;
566fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
56781338031SDmitry Chagin 	ksi.ksi_errno = 0;
56881338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
56981338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
57081338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
5719b44bfc5SAlexander Leidinger }
5729b44bfc5SAlexander Leidinger 
57381338031SDmitry Chagin /*
57481338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
57581338031SDmitry Chagin  */
5769b44bfc5SAlexander Leidinger int
5779b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5789b44bfc5SAlexander Leidinger {
57981338031SDmitry Chagin 	struct thread *tdt;
58081338031SDmitry Chagin 	ksiginfo_t ksi;
58181338031SDmitry Chagin 	int sig;
58281338031SDmitry Chagin 
5839b44bfc5SAlexander Leidinger #ifdef DEBUG
5849b44bfc5SAlexander Leidinger 	if (ldebug(tkill))
5859b44bfc5SAlexander Leidinger 		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
5869b44bfc5SAlexander Leidinger #endif
587aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
588aa8b2011SKonstantin Belousov 		return (EINVAL);
5899b44bfc5SAlexander Leidinger 
59081338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
59181338031SDmitry Chagin 		return (EINVAL);
59281338031SDmitry Chagin 
5934ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
59481338031SDmitry Chagin 
59581338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
59681338031SDmitry Chagin 	if (tdt == NULL)
59781338031SDmitry Chagin 		return (ESRCH);
59881338031SDmitry Chagin 
59981338031SDmitry Chagin 	ksiginfo_init(&ksi);
60081338031SDmitry Chagin 	ksi.ksi_signo = sig;
601fe4ed1e7SDmitry Chagin 	ksi.ksi_code = SI_LWP;
60281338031SDmitry Chagin 	ksi.ksi_errno = 0;
60381338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
60481338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
60581338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
606aa8b2011SKonstantin Belousov }
607aa8b2011SKonstantin Belousov 
608aa8b2011SKonstantin Belousov void
609fe4ed1e7SDmitry Chagin ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
610aa8b2011SKonstantin Belousov {
611aa8b2011SKonstantin Belousov 
612fe4ed1e7SDmitry Chagin 	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
613fe4ed1e7SDmitry Chagin }
614aa8b2011SKonstantin Belousov 
615fe4ed1e7SDmitry Chagin static void
616fe4ed1e7SDmitry Chagin sicode_to_lsicode(int si_code, int *lsi_code)
617fe4ed1e7SDmitry Chagin {
618fe4ed1e7SDmitry Chagin 
619fe4ed1e7SDmitry Chagin 	switch (si_code) {
620fe4ed1e7SDmitry Chagin 	case SI_USER:
621fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_USER;
622fe4ed1e7SDmitry Chagin 		break;
623fe4ed1e7SDmitry Chagin 	case SI_KERNEL:
624fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_KERNEL;
625fe4ed1e7SDmitry Chagin 		break;
626fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
627fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_QUEUE;
628fe4ed1e7SDmitry Chagin 		break;
629fe4ed1e7SDmitry Chagin 	case SI_TIMER:
630fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TIMER;
631fe4ed1e7SDmitry Chagin 		break;
632fe4ed1e7SDmitry Chagin 	case SI_MESGQ:
633fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_MESGQ;
634fe4ed1e7SDmitry Chagin 		break;
635fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
636fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_ASYNCIO;
637fe4ed1e7SDmitry Chagin 		break;
638fe4ed1e7SDmitry Chagin 	case SI_LWP:
639fe4ed1e7SDmitry Chagin 		*lsi_code = LINUX_SI_TKILL;
640fe4ed1e7SDmitry Chagin 		break;
641fe4ed1e7SDmitry Chagin 	default:
642fe4ed1e7SDmitry Chagin 		*lsi_code = si_code;
643fe4ed1e7SDmitry Chagin 		break;
644fe4ed1e7SDmitry Chagin 	}
645fe4ed1e7SDmitry Chagin }
646fe4ed1e7SDmitry Chagin 
647fe4ed1e7SDmitry Chagin void
648fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
649fe4ed1e7SDmitry Chagin {
650fe4ed1e7SDmitry Chagin 
651fe4ed1e7SDmitry Chagin 	/* sig alredy converted */
652fe4ed1e7SDmitry Chagin 	lsi->lsi_signo = sig;
653fe4ed1e7SDmitry Chagin 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
654fe4ed1e7SDmitry Chagin 
655fe4ed1e7SDmitry Chagin 	switch (si->si_code) {
656fe4ed1e7SDmitry Chagin 	case SI_LWP:
657fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
658fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
659fe4ed1e7SDmitry Chagin 		break;
660fe4ed1e7SDmitry Chagin 
661fe4ed1e7SDmitry Chagin 	case SI_TIMER:
662fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
663fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
664fe4ed1e7SDmitry Chagin 		lsi->lsi_tid = si->si_timerid;
665fe4ed1e7SDmitry Chagin 		break;
666fe4ed1e7SDmitry Chagin 
667fe4ed1e7SDmitry Chagin 	case SI_QUEUE:
668fe4ed1e7SDmitry Chagin 		lsi->lsi_pid = si->si_pid;
669fe4ed1e7SDmitry Chagin 		lsi->lsi_uid = si->si_uid;
670fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
671fe4ed1e7SDmitry Chagin 		break;
672fe4ed1e7SDmitry Chagin 
673fe4ed1e7SDmitry Chagin 	case SI_ASYNCIO:
674fe4ed1e7SDmitry Chagin 		lsi->lsi_int = si->si_value.sival_int;
675fe4ed1e7SDmitry Chagin 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
676fe4ed1e7SDmitry Chagin 		break;
677fe4ed1e7SDmitry Chagin 
678fe4ed1e7SDmitry Chagin 	default:
679aa8b2011SKonstantin Belousov 		switch (sig) {
680aa8b2011SKonstantin Belousov 		case LINUX_SIGPOLL:
681aa8b2011SKonstantin Belousov 			/* XXX si_fd? */
682fe4ed1e7SDmitry Chagin 			lsi->lsi_band = si->si_band;
683aa8b2011SKonstantin Belousov 			break;
684fe4ed1e7SDmitry Chagin 
685aa8b2011SKonstantin Belousov 		case LINUX_SIGCHLD:
686fe4ed1e7SDmitry Chagin 			lsi->lsi_errno = 0;
687fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
688fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
689fe4ed1e7SDmitry Chagin 
690fe4ed1e7SDmitry Chagin 			if (si->si_code == CLD_STOPPED)
6914ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
692fe4ed1e7SDmitry Chagin 			else if (si->si_code == CLD_CONTINUED)
6934ab7403bSDmitry Chagin 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
694fe4ed1e7SDmitry Chagin 			else
695fe4ed1e7SDmitry Chagin 				lsi->lsi_status = si->si_status;
696aa8b2011SKonstantin Belousov 			break;
697fe4ed1e7SDmitry Chagin 
698aa8b2011SKonstantin Belousov 		case LINUX_SIGBUS:
699aa8b2011SKonstantin Belousov 		case LINUX_SIGILL:
700aa8b2011SKonstantin Belousov 		case LINUX_SIGFPE:
701aa8b2011SKonstantin Belousov 		case LINUX_SIGSEGV:
702fe4ed1e7SDmitry Chagin 			lsi->lsi_addr = PTROUT(si->si_addr);
703aa8b2011SKonstantin Belousov 			break;
704fe4ed1e7SDmitry Chagin 
705aa8b2011SKonstantin Belousov 		default:
706fe4ed1e7SDmitry Chagin 			lsi->lsi_pid = si->si_pid;
707fe4ed1e7SDmitry Chagin 			lsi->lsi_uid = si->si_uid;
708fe4ed1e7SDmitry Chagin 			if (sig >= LINUX_SIGRTMIN) {
709fe4ed1e7SDmitry Chagin 				lsi->lsi_int = si->si_value.sival_int;
710fe4ed1e7SDmitry Chagin 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
711fe4ed1e7SDmitry Chagin 			}
712aa8b2011SKonstantin Belousov 			break;
713aa8b2011SKonstantin Belousov 		}
714fe4ed1e7SDmitry Chagin 		break;
71509d6cb0aSDmitry Chagin 	}
7169b44bfc5SAlexander Leidinger }
7177ac9766dSDmitry Chagin 
7187ac9766dSDmitry Chagin void
7197ac9766dSDmitry Chagin lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
7207ac9766dSDmitry Chagin {
7217ac9766dSDmitry Chagin 
7227ac9766dSDmitry Chagin 	ksi->ksi_signo = sig;
7237ac9766dSDmitry Chagin 	ksi->ksi_code = lsi->lsi_code;	/* XXX. Convert. */
7247ac9766dSDmitry Chagin 	ksi->ksi_pid = lsi->lsi_pid;
7257ac9766dSDmitry Chagin 	ksi->ksi_uid = lsi->lsi_uid;
7267ac9766dSDmitry Chagin 	ksi->ksi_status = lsi->lsi_status;
7277ac9766dSDmitry Chagin 	ksi->ksi_addr = PTRIN(lsi->lsi_addr);
7287ac9766dSDmitry Chagin 	ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
7297ac9766dSDmitry Chagin }
7307ac9766dSDmitry Chagin 
7317ac9766dSDmitry Chagin int
7327ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
7337ac9766dSDmitry Chagin {
7347ac9766dSDmitry Chagin 	l_siginfo_t linfo;
7357ac9766dSDmitry Chagin 	struct proc *p;
7367ac9766dSDmitry Chagin 	ksiginfo_t ksi;
7377ac9766dSDmitry Chagin 	int error;
7387ac9766dSDmitry Chagin 	int sig;
7397ac9766dSDmitry Chagin 
7407ac9766dSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
7417ac9766dSDmitry Chagin 		return (EINVAL);
7427ac9766dSDmitry Chagin 
7437ac9766dSDmitry Chagin 	error = copyin(args->info, &linfo, sizeof(linfo));
7447ac9766dSDmitry Chagin 	if (error != 0)
7457ac9766dSDmitry Chagin 		return (error);
7467ac9766dSDmitry Chagin 
7477ac9766dSDmitry Chagin 	if (linfo.lsi_code >= 0)
7487ac9766dSDmitry Chagin 		return (EPERM);
7497ac9766dSDmitry Chagin 
7504ab7403bSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
7517ac9766dSDmitry Chagin 
7527ac9766dSDmitry Chagin 	error = ESRCH;
753537d0fb1SMateusz Guzik 	if ((p = pfind_any(args->pid)) != NULL) {
7547ac9766dSDmitry Chagin 		error = p_cansignal(td, p, sig);
7557ac9766dSDmitry Chagin 		if (error != 0) {
7567ac9766dSDmitry Chagin 			PROC_UNLOCK(p);
7577ac9766dSDmitry Chagin 			return (error);
7587ac9766dSDmitry Chagin 		}
7597ac9766dSDmitry Chagin 
7607ac9766dSDmitry Chagin 		ksiginfo_init(&ksi);
7617ac9766dSDmitry Chagin 		lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
7627ac9766dSDmitry Chagin 		error = tdsendsignal(p, NULL, sig, &ksi);
7637ac9766dSDmitry Chagin 		PROC_UNLOCK(p);
7647ac9766dSDmitry Chagin 	}
7657ac9766dSDmitry Chagin 
7667ac9766dSDmitry Chagin 	return (error);
7677ac9766dSDmitry Chagin }
768486a06bdSDmitry Chagin 
769486a06bdSDmitry Chagin int
770486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
771486a06bdSDmitry Chagin {
772486a06bdSDmitry Chagin 	l_siginfo_t linfo;
773486a06bdSDmitry Chagin 	struct thread *tds;
774486a06bdSDmitry Chagin 	ksiginfo_t ksi;
775486a06bdSDmitry Chagin 	int error;
776486a06bdSDmitry Chagin 	int sig;
777486a06bdSDmitry Chagin 
778486a06bdSDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
779486a06bdSDmitry Chagin 		return (EINVAL);
780486a06bdSDmitry Chagin 
781486a06bdSDmitry Chagin 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
782486a06bdSDmitry Chagin 	if (error != 0)
783486a06bdSDmitry Chagin 		return (error);
784486a06bdSDmitry Chagin 
785486a06bdSDmitry Chagin 	if (linfo.lsi_code >= 0)
786486a06bdSDmitry Chagin 		return (EPERM);
787486a06bdSDmitry Chagin 
788486a06bdSDmitry Chagin 	tds = linux_tdfind(td, args->tid, args->tgid);
789486a06bdSDmitry Chagin 	if (tds == NULL)
790486a06bdSDmitry Chagin 		return (ESRCH);
791486a06bdSDmitry Chagin 
792486a06bdSDmitry Chagin 	sig = linux_to_bsd_signal(args->sig);
793486a06bdSDmitry Chagin 	ksiginfo_init(&ksi);
794486a06bdSDmitry Chagin 	lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
795486a06bdSDmitry Chagin 	return (linux_do_tkill(td, tds, &ksi));
796486a06bdSDmitry Chagin }
797