xref: /freebsd/sys/compat/linux/linux_signal.c (revision 9a14aa017b21c292740c00ee098195cd46642730)
1c21dee17SSøren Schmidt /*-
2*9a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
3c21dee17SSøren Schmidt  * All rights reserved.
4c21dee17SSøren Schmidt  *
5c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
6c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
7c21dee17SSøren Schmidt  * are met:
8c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
9c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer
10c21dee17SSøren Schmidt  *    in this position and unchanged.
11c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
12c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
13c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
14c21dee17SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
1521dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
16c21dee17SSøren Schmidt  *
17c21dee17SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18c21dee17SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c21dee17SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20c21dee17SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21c21dee17SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22c21dee17SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c21dee17SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c21dee17SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c21dee17SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26c21dee17SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c21dee17SSøren Schmidt  */
28c21dee17SSøren Schmidt 
2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h>
301e8d246eSNate Lawson __FBSDID("$FreeBSD$");
3116dbc7f2SDavid E. O'Brien 
32c21dee17SSøren Schmidt #include <sys/param.h>
33c21dee17SSøren Schmidt #include <sys/systm.h>
34fb919e4dSMark Murray #include <sys/lock.h>
35fb919e4dSMark Murray #include <sys/mutex.h>
3629ddc19bSAlexander Leidinger #include <sys/sx.h>
37c21dee17SSøren Schmidt #include <sys/proc.h>
38c21dee17SSøren Schmidt #include <sys/signalvar.h>
39206a5d3aSIan Dowse #include <sys/syscallsubr.h>
40fb919e4dSMark Murray #include <sys/sysproto.h>
41c21dee17SSøren Schmidt 
42aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
43aa8b2011SKonstantin Belousov 
44aefce619SRuslan Ermilov #include "opt_compat.h"
45aefce619SRuslan Ermilov 
461997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
474af27623STim J. Robbins #include <machine/../linux32/linux.h>
484af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
491997c537SDavid E. O'Brien #else
501997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
511997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
524af27623STim J. Robbins #endif
53ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
559b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
569b44bfc5SAlexander Leidinger 
57ba9ef45bSMarcel Moolenaar void
585002a60fSMarcel Moolenaar linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
59956d3333SMarcel Moolenaar {
60d66a5066SPeter Wemm 	int b, l;
61c21dee17SSøren Schmidt 
62956d3333SMarcel Moolenaar 	SIGEMPTYSET(*bss);
63956d3333SMarcel Moolenaar 	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
64956d3333SMarcel Moolenaar 	bss->__bits[1] = lss->__bits[1];
65956d3333SMarcel Moolenaar 	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
66956d3333SMarcel Moolenaar 		if (LINUX_SIGISMEMBER(*lss, l)) {
67956d3333SMarcel Moolenaar 			b = linux_to_bsd_signal[_SIG_IDX(l)];
68956d3333SMarcel Moolenaar 			if (b)
69956d3333SMarcel Moolenaar 				SIGADDSET(*bss, b);
70d66a5066SPeter Wemm 		}
71d66a5066SPeter Wemm 	}
72c21dee17SSøren Schmidt }
73c21dee17SSøren Schmidt 
7479363394SAndrew Gallatin void
755002a60fSMarcel Moolenaar bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
76956d3333SMarcel Moolenaar {
77d66a5066SPeter Wemm 	int b, l;
78c21dee17SSøren Schmidt 
79956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(*lss);
80956d3333SMarcel Moolenaar 	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
81956d3333SMarcel Moolenaar 	lss->__bits[1] = bss->__bits[1];
82956d3333SMarcel Moolenaar 	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
83956d3333SMarcel Moolenaar 		if (SIGISMEMBER(*bss, b)) {
84956d3333SMarcel Moolenaar 			l = bsd_to_linux_signal[_SIG_IDX(b)];
85956d3333SMarcel Moolenaar 			if (l)
86956d3333SMarcel Moolenaar 				LINUX_SIGADDSET(*lss, l);
87d66a5066SPeter Wemm 		}
88d66a5066SPeter Wemm 	}
89c21dee17SSøren Schmidt }
90c21dee17SSøren Schmidt 
91a1ebcbfbSPeter Wemm static void
925002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
93d66a5066SPeter Wemm {
94956d3333SMarcel Moolenaar 
95956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
964af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
97d66a5066SPeter Wemm 	bsa->sa_flags = 0;
988f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
99d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
10006ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
10106ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
10206ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
10306ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
1048f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
105d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
1068f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_RESTART)
107d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
1088f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
109d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
1108f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOMASK)
111d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
112d66a5066SPeter Wemm }
113d66a5066SPeter Wemm 
114a1ebcbfbSPeter Wemm static void
1155002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
116d66a5066SPeter Wemm {
117956d3333SMarcel Moolenaar 
118956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1191997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1204af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1214af27623STim J. Robbins #else
1228f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1234af27623STim J. Robbins #endif
1244af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1258f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
126d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1278f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
12806ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
12906ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
13006ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
13106ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
132d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1338f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
134d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1358f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
136d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1378f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
138d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1398f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
140d66a5066SPeter Wemm }
141c21dee17SSøren Schmidt 
142ba9ef45bSMarcel Moolenaar int
143b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1445002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
14506ebbe77SMarcel Moolenaar {
146206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
147206a5d3aSIan Dowse 	int error, sig;
14806ebbe77SMarcel Moolenaar 
149687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
150956d3333SMarcel Moolenaar 		return (EINVAL);
15106ebbe77SMarcel Moolenaar 
152206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
153956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
154206a5d3aSIan Dowse 		nsa = &act;
155ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
156206a5d3aSIan Dowse 	} else
15706ebbe77SMarcel Moolenaar 		nsa = NULL;
15806ebbe77SMarcel Moolenaar 
159956d3333SMarcel Moolenaar 	if (linux_sig <= LINUX_SIGTBLSZ)
160206a5d3aSIan Dowse 		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
161956d3333SMarcel Moolenaar 	else
162206a5d3aSIan Dowse 		sig = linux_sig;
163956d3333SMarcel Moolenaar 
164206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
16506ebbe77SMarcel Moolenaar 	if (error)
166956d3333SMarcel Moolenaar 		return (error);
16706ebbe77SMarcel Moolenaar 
168ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
169ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
17006ebbe77SMarcel Moolenaar 
171956d3333SMarcel Moolenaar 	return (0);
17206ebbe77SMarcel Moolenaar }
17306ebbe77SMarcel Moolenaar 
1745231fb20SDavid E. O'Brien 
175c21dee17SSøren Schmidt int
176b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
177d66a5066SPeter Wemm {
1785002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
179d66a5066SPeter Wemm 	int error;
180d66a5066SPeter Wemm 
181d66a5066SPeter Wemm #ifdef DEBUG
18224593369SJonathan Lemon 	if (ldebug(signal))
18324593369SJonathan Lemon 		printf(ARGS(signal, "%d, %p"),
184b61c60d4SDavid E. O'Brien 		    args->sig, (void *)(uintptr_t)args->handler);
185d66a5066SPeter Wemm #endif
186d66a5066SPeter Wemm 
18706ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
18806ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
189956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
190d66a5066SPeter Wemm 
191b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1924af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
193d66a5066SPeter Wemm 
194956d3333SMarcel Moolenaar 	return (error);
195d66a5066SPeter Wemm }
196d66a5066SPeter Wemm 
197c21dee17SSøren Schmidt int
198b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
199c21dee17SSøren Schmidt {
2005002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
20106ebbe77SMarcel Moolenaar 	int error;
202c21dee17SSøren Schmidt 
203c21dee17SSøren Schmidt #ifdef DEBUG
20424593369SJonathan Lemon 	if (ldebug(rt_sigaction))
20524593369SJonathan Lemon 		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
20624593369SJonathan Lemon 		    (long)args->sig, (void *)args->act,
2075231fb20SDavid E. O'Brien 		    (void *)args->oact, (long)args->sigsetsize);
208c21dee17SSøren Schmidt #endif
209d66a5066SPeter Wemm 
2105002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
211956d3333SMarcel Moolenaar 		return (EINVAL);
21206ebbe77SMarcel Moolenaar 
213956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2145002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21506ebbe77SMarcel Moolenaar 		if (error)
216956d3333SMarcel Moolenaar 			return (error);
21706ebbe77SMarcel Moolenaar 	}
21806ebbe77SMarcel Moolenaar 
219b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
22006ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
22106ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
22206ebbe77SMarcel Moolenaar 
223956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2245002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22506ebbe77SMarcel Moolenaar 	}
22606ebbe77SMarcel Moolenaar 
227956d3333SMarcel Moolenaar 	return (error);
22806ebbe77SMarcel Moolenaar }
22906ebbe77SMarcel Moolenaar 
23006ebbe77SMarcel Moolenaar static int
231b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2325002a60fSMarcel Moolenaar 		     l_sigset_t *old)
23306ebbe77SMarcel Moolenaar {
234fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
235fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
236216af822SJohn Baldwin 	int error;
23706ebbe77SMarcel Moolenaar 
238b40ce416SJulian Elischer 	td->td_retval[0] = 0;
239d66a5066SPeter Wemm 
24019dde5cdSJohn Baldwin 	switch (how) {
24119dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
24219dde5cdSJohn Baldwin 		how = SIG_BLOCK;
24319dde5cdSJohn Baldwin 		break;
24419dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
24519dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
24619dde5cdSJohn Baldwin 		break;
24719dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
24819dde5cdSJohn Baldwin 		how = SIG_SETMASK;
24919dde5cdSJohn Baldwin 		break;
25019dde5cdSJohn Baldwin 	default:
25119dde5cdSJohn Baldwin 		return (EINVAL);
25219dde5cdSJohn Baldwin 	}
25306ebbe77SMarcel Moolenaar 	if (new != NULL) {
254fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
255fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
256fe8cdcaeSJohn Baldwin 	} else
257fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
25819dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2592f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
260fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
26106ebbe77SMarcel Moolenaar 
262956d3333SMarcel Moolenaar 	return (error);
26306ebbe77SMarcel Moolenaar }
26406ebbe77SMarcel Moolenaar 
26506ebbe77SMarcel Moolenaar int
266b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
26706ebbe77SMarcel Moolenaar {
2685002a60fSMarcel Moolenaar 	l_osigset_t mask;
2695002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
27006ebbe77SMarcel Moolenaar 	int error;
27106ebbe77SMarcel Moolenaar 
27206ebbe77SMarcel Moolenaar #ifdef DEBUG
27324593369SJonathan Lemon 	if (ldebug(sigprocmask))
27424593369SJonathan Lemon 		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
27506ebbe77SMarcel Moolenaar #endif
27606ebbe77SMarcel Moolenaar 
27706ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2785002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
27906ebbe77SMarcel Moolenaar 		if (error)
280956d3333SMarcel Moolenaar 			return (error);
281956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
282956d3333SMarcel Moolenaar 		set.__bits[0] = mask;
28306ebbe77SMarcel Moolenaar 	}
28406ebbe77SMarcel Moolenaar 
285b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
286956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
287956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
28806ebbe77SMarcel Moolenaar 
289956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
290956d3333SMarcel Moolenaar 		mask = oset.__bits[0];
2915002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
29206ebbe77SMarcel Moolenaar 	}
29306ebbe77SMarcel Moolenaar 
294956d3333SMarcel Moolenaar 	return (error);
29506ebbe77SMarcel Moolenaar }
29606ebbe77SMarcel Moolenaar 
29706ebbe77SMarcel Moolenaar int
298b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
29906ebbe77SMarcel Moolenaar {
3005002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
30106ebbe77SMarcel Moolenaar 	int error;
30206ebbe77SMarcel Moolenaar 
30306ebbe77SMarcel Moolenaar #ifdef DEBUG
30424593369SJonathan Lemon 	if (ldebug(rt_sigprocmask))
30524593369SJonathan Lemon 		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
30624593369SJonathan Lemon 		    args->how, (void *)args->mask,
3075231fb20SDavid E. O'Brien 		    (void *)args->omask, (long)args->sigsetsize);
30806ebbe77SMarcel Moolenaar #endif
30906ebbe77SMarcel Moolenaar 
3105002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
31106ebbe77SMarcel Moolenaar 		return EINVAL;
31206ebbe77SMarcel Moolenaar 
31306ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3145002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
31506ebbe77SMarcel Moolenaar 		if (error)
316956d3333SMarcel Moolenaar 			return (error);
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) {
3245002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
32506ebbe77SMarcel Moolenaar 	}
32606ebbe77SMarcel Moolenaar 
327956d3333SMarcel Moolenaar 	return (error);
328c21dee17SSøren Schmidt }
329c21dee17SSøren Schmidt 
330c21dee17SSøren Schmidt int
331b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
332c21dee17SSøren Schmidt {
333b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3345002a60fSMarcel Moolenaar 	l_sigset_t mask;
335956d3333SMarcel Moolenaar 
336c21dee17SSøren Schmidt #ifdef DEBUG
3375002a60fSMarcel Moolenaar 	if (ldebug(sgetmask))
3385002a60fSMarcel Moolenaar 		printf(ARGS(sgetmask, ""));
339c21dee17SSøren Schmidt #endif
340956d3333SMarcel Moolenaar 
341216af822SJohn Baldwin 	PROC_LOCK(p);
3424093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
343216af822SJohn Baldwin 	PROC_UNLOCK(p);
344b40ce416SJulian Elischer 	td->td_retval[0] = mask.__bits[0];
345956d3333SMarcel Moolenaar 	return (0);
346c21dee17SSøren Schmidt }
347c21dee17SSøren Schmidt 
348c21dee17SSøren Schmidt int
349b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
350c21dee17SSøren Schmidt {
351b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3525002a60fSMarcel Moolenaar 	l_sigset_t lset;
353956d3333SMarcel Moolenaar 	sigset_t bset;
354c21dee17SSøren Schmidt 
355c21dee17SSøren Schmidt #ifdef DEBUG
3565002a60fSMarcel Moolenaar 	if (ldebug(ssetmask))
3575002a60fSMarcel Moolenaar 		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
358c21dee17SSøren Schmidt #endif
359d66a5066SPeter Wemm 
360216af822SJohn Baldwin 	PROC_LOCK(p);
3614093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
362b40ce416SJulian Elischer 	td->td_retval[0] = lset.__bits[0];
363956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
364956d3333SMarcel Moolenaar 	lset.__bits[0] = args->mask;
365956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3664093529dSJeff Roberson 	td->td_sigmask = bset;
3674093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3684093529dSJeff Roberson 	signotify(td);
369216af822SJohn Baldwin 	PROC_UNLOCK(p);
370956d3333SMarcel Moolenaar 	return (0);
371c21dee17SSøren Schmidt }
372c21dee17SSøren Schmidt 
3735d58e285STim J. Robbins /*
3745d58e285STim J. Robbins  * MPSAFE
3755d58e285STim J. Robbins  */
376c21dee17SSøren Schmidt int
377b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
378c21dee17SSøren Schmidt {
379b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
380956d3333SMarcel Moolenaar 	sigset_t bset;
3815002a60fSMarcel Moolenaar 	l_sigset_t lset;
3825002a60fSMarcel Moolenaar 	l_osigset_t mask;
383c21dee17SSøren Schmidt 
384c21dee17SSøren Schmidt #ifdef DEBUG
38524593369SJonathan Lemon 	if (ldebug(sigpending))
38624593369SJonathan Lemon 		printf(ARGS(sigpending, "*"));
387c21dee17SSøren Schmidt #endif
388956d3333SMarcel Moolenaar 
389216af822SJohn Baldwin 	PROC_LOCK(p);
3901d9c5696SJuli Mallett 	bset = p->p_siglist;
3914093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3924093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
393216af822SJohn Baldwin 	PROC_UNLOCK(p);
3949d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
395956d3333SMarcel Moolenaar 	mask = lset.__bits[0];
396956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
397c21dee17SSøren Schmidt }
39817138b61SAlexander Leidinger 
39917138b61SAlexander Leidinger /*
40017138b61SAlexander Leidinger  * MPSAFE
40117138b61SAlexander Leidinger  */
40217138b61SAlexander Leidinger int
40317138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
40417138b61SAlexander Leidinger {
40517138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
40617138b61SAlexander Leidinger 	sigset_t bset;
40717138b61SAlexander Leidinger 	l_sigset_t lset;
40817138b61SAlexander Leidinger 
40917138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
41017138b61SAlexander Leidinger 		return EINVAL;
41117138b61SAlexander Leidinger 		/* NOT REACHED */
41217138b61SAlexander Leidinger 
41317138b61SAlexander Leidinger #ifdef DEBUG
41417138b61SAlexander Leidinger 	if (ldebug(rt_sigpending))
41517138b61SAlexander Leidinger 		printf(ARGS(rt_sigpending, "*"));
41617138b61SAlexander Leidinger #endif
41717138b61SAlexander Leidinger 
41817138b61SAlexander Leidinger 	PROC_LOCK(p);
41917138b61SAlexander Leidinger 	bset = p->p_siglist;
42017138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
42117138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
42217138b61SAlexander Leidinger 	PROC_UNLOCK(p);
42317138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
42417138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
42517138b61SAlexander Leidinger }
426c21dee17SSøren Schmidt 
427c9447c75SAlexander Leidinger /*
428c9447c75SAlexander Leidinger  * MPSAFE
429c9447c75SAlexander Leidinger  */
430c9447c75SAlexander Leidinger int
431c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
432c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
433c9447c75SAlexander Leidinger {
434f3481dd9SDmitry Chagin 	int error, sig;
435c9447c75SAlexander Leidinger 	l_timeval ltv;
436c9447c75SAlexander Leidinger 	struct timeval tv;
437c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
438c9447c75SAlexander Leidinger 	l_sigset_t lset;
439c9447c75SAlexander Leidinger 	sigset_t bset;
440c9447c75SAlexander Leidinger 	l_siginfo_t linfo;
441c9447c75SAlexander Leidinger 	ksiginfo_t info;
442c9447c75SAlexander Leidinger 
443c9447c75SAlexander Leidinger #ifdef DEBUG
444c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
445c9447c75SAlexander Leidinger 		printf(ARGS(rt_sigtimedwait, "*"));
446c9447c75SAlexander Leidinger #endif
447c9447c75SAlexander Leidinger 	if (args->sigsetsize != sizeof(l_sigset_t))
448c9447c75SAlexander Leidinger 		return (EINVAL);
449c9447c75SAlexander Leidinger 
450c9447c75SAlexander Leidinger 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
451c9447c75SAlexander Leidinger 		return (error);
452c9447c75SAlexander Leidinger 	linux_to_bsd_sigset(&lset, &bset);
453c9447c75SAlexander Leidinger 
454c9447c75SAlexander Leidinger 	tsa = NULL;
455c9447c75SAlexander Leidinger 	if (args->timeout) {
456c9447c75SAlexander Leidinger 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
457c9447c75SAlexander Leidinger 			return (error);
458c9447c75SAlexander Leidinger #ifdef DEBUG
459c9447c75SAlexander Leidinger 		if (ldebug(rt_sigtimedwait))
4608c50c562SDmitry Chagin 			printf(LMSG("linux_rt_sigtimedwait: "
4618c50c562SDmitry Chagin 			    "incoming timeout (%d/%d)\n"),
462c9447c75SAlexander Leidinger 			    ltv.tv_sec, ltv.tv_usec);
463c9447c75SAlexander Leidinger #endif
464c9447c75SAlexander Leidinger 		tv.tv_sec = (long)ltv.tv_sec;
465c9447c75SAlexander Leidinger 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
466c9447c75SAlexander Leidinger 		if (itimerfix(&tv)) {
467c9447c75SAlexander Leidinger 			/*
468c9447c75SAlexander Leidinger 			 * The timeout was invalid. Convert it to something
469c9447c75SAlexander Leidinger 			 * valid that will act as it does under Linux.
470c9447c75SAlexander Leidinger 			 */
471c9447c75SAlexander Leidinger 			tv.tv_sec += tv.tv_usec / 1000000;
472c9447c75SAlexander Leidinger 			tv.tv_usec %= 1000000;
473c9447c75SAlexander Leidinger 			if (tv.tv_usec < 0) {
474c9447c75SAlexander Leidinger 				tv.tv_sec -= 1;
475c9447c75SAlexander Leidinger 				tv.tv_usec += 1000000;
476c9447c75SAlexander Leidinger 			}
477c9447c75SAlexander Leidinger 			if (tv.tv_sec < 0)
478c9447c75SAlexander Leidinger 				timevalclear(&tv);
479c9447c75SAlexander Leidinger #ifdef DEBUG
480c9447c75SAlexander Leidinger 			if (ldebug(rt_sigtimedwait))
4818c50c562SDmitry Chagin 				printf(LMSG("linux_rt_sigtimedwait: "
4828c50c562SDmitry Chagin 				    "converted timeout (%jd/%ld)\n"),
48359038483SXin LI 				    (intmax_t)tv.tv_sec, tv.tv_usec);
484c9447c75SAlexander Leidinger #endif
485c9447c75SAlexander Leidinger 		}
486c9447c75SAlexander Leidinger 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
487c9447c75SAlexander Leidinger 		tsa = &ts;
488c9447c75SAlexander Leidinger 	}
489c9447c75SAlexander Leidinger 	error = kern_sigtimedwait(td, bset, &info, tsa);
490c9447c75SAlexander Leidinger #ifdef DEBUG
491c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
4928c50c562SDmitry Chagin 		printf(LMSG("linux_rt_sigtimedwait: "
4938c50c562SDmitry Chagin 		    "sigtimedwait returning (%d)\n"), error);
494c9447c75SAlexander Leidinger #endif
495c9447c75SAlexander Leidinger 	if (error)
496c9447c75SAlexander Leidinger 		return (error);
497c9447c75SAlexander Leidinger 
498f3481dd9SDmitry Chagin 	sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
499f3481dd9SDmitry Chagin 
500c9447c75SAlexander Leidinger 	if (args->ptr) {
501c9447c75SAlexander Leidinger 		memset(&linfo, 0, sizeof(linfo));
502f3481dd9SDmitry Chagin 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
503c9447c75SAlexander Leidinger 		error = copyout(&linfo, args->ptr, sizeof(linfo));
504c9447c75SAlexander Leidinger 	}
505f3481dd9SDmitry Chagin 	if (error == 0)
506f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
507c9447c75SAlexander Leidinger 
508c9447c75SAlexander Leidinger 	return (error);
509c9447c75SAlexander Leidinger }
510c9447c75SAlexander Leidinger 
511c21dee17SSøren Schmidt int
512b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
513c21dee17SSøren Schmidt {
514ef04503dSPeter Wemm 	struct kill_args /* {
515c21dee17SSøren Schmidt 	    int pid;
516c21dee17SSøren Schmidt 	    int signum;
517ef04503dSPeter Wemm 	} */ tmp;
518c21dee17SSøren Schmidt 
519c21dee17SSøren Schmidt #ifdef DEBUG
52024593369SJonathan Lemon 	if (ldebug(kill))
52124593369SJonathan Lemon 		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
522c21dee17SSøren Schmidt #endif
523956d3333SMarcel Moolenaar 
524956d3333SMarcel Moolenaar 	/*
525956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
526956d3333SMarcel Moolenaar 	 */
52764742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5289a6a64d3SDmitry Chagin 		return (EINVAL);
529956d3333SMarcel Moolenaar 
530956d3333SMarcel Moolenaar 	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
531956d3333SMarcel Moolenaar 		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
532956d3333SMarcel Moolenaar 	else
533956d3333SMarcel Moolenaar 		tmp.signum = args->signum;
534956d3333SMarcel Moolenaar 
535c21dee17SSøren Schmidt 	tmp.pid = args->pid;
5368451d0ddSKip Macy 	return (sys_kill(td, &tmp));
537c21dee17SSøren Schmidt }
5389b44bfc5SAlexander Leidinger 
539aa8b2011SKonstantin Belousov static int
540aa8b2011SKonstantin Belousov linux_do_tkill(struct thread *td, l_int tgid, l_int pid, l_int signum)
541aa8b2011SKonstantin Belousov {
542aa8b2011SKonstantin Belousov 	struct proc *proc = td->td_proc;
543aa8b2011SKonstantin Belousov 	struct linux_emuldata *em;
544aa8b2011SKonstantin Belousov 	struct proc *p;
545aa8b2011SKonstantin Belousov 	ksiginfo_t ksi;
546aa8b2011SKonstantin Belousov 	int error;
547aa8b2011SKonstantin Belousov 
54814961ba7SRobert Watson 	AUDIT_ARG_SIGNUM(signum);
54914961ba7SRobert Watson 	AUDIT_ARG_PID(pid);
550aa8b2011SKonstantin Belousov 
551aa8b2011SKonstantin Belousov 	/*
552aa8b2011SKonstantin Belousov 	 * Allow signal 0 as a means to check for privileges
553aa8b2011SKonstantin Belousov 	 */
554aa8b2011SKonstantin Belousov 	if (!LINUX_SIG_VALID(signum) && signum != 0)
555aa8b2011SKonstantin Belousov 		return (EINVAL);
556aa8b2011SKonstantin Belousov 
557aa8b2011SKonstantin Belousov 	if (signum > 0 && signum <= LINUX_SIGTBLSZ)
558aa8b2011SKonstantin Belousov 		signum = linux_to_bsd_signal[_SIG_IDX(signum)];
559aa8b2011SKonstantin Belousov 
560aa8b2011SKonstantin Belousov 	if ((p = pfind(pid)) == NULL) {
561aa8b2011SKonstantin Belousov 		if ((p = zpfind(pid)) == NULL)
562aa8b2011SKonstantin Belousov 			return (ESRCH);
563aa8b2011SKonstantin Belousov 	}
564aa8b2011SKonstantin Belousov 
56514961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
566aa8b2011SKonstantin Belousov 	error = p_cansignal(td, p, signum);
5679ae781dfSKonstantin Belousov 	if (error != 0 || signum == 0)
568aa8b2011SKonstantin Belousov 		goto out;
569aa8b2011SKonstantin Belousov 
570aa8b2011SKonstantin Belousov 	error = ESRCH;
571aa8b2011SKonstantin Belousov 	em = em_find(p, EMUL_DONTLOCK);
572aa8b2011SKonstantin Belousov 
573aa8b2011SKonstantin Belousov 	if (em == NULL) {
574aa8b2011SKonstantin Belousov #ifdef DEBUG
575aa8b2011SKonstantin Belousov 		printf("emuldata not found in do_tkill.\n");
576aa8b2011SKonstantin Belousov #endif
577aa8b2011SKonstantin Belousov 		goto out;
578aa8b2011SKonstantin Belousov 	}
579aa8b2011SKonstantin Belousov 	if (tgid > 0 && em->shared->group_pid != tgid)
580aa8b2011SKonstantin Belousov 		goto out;
581aa8b2011SKonstantin Belousov 
582aa8b2011SKonstantin Belousov 	ksiginfo_init(&ksi);
583aa8b2011SKonstantin Belousov 	ksi.ksi_signo = signum;
584aa8b2011SKonstantin Belousov 	ksi.ksi_code = LINUX_SI_TKILL;
585aa8b2011SKonstantin Belousov 	ksi.ksi_errno = 0;
586aa8b2011SKonstantin Belousov 	ksi.ksi_pid = proc->p_pid;
587aa8b2011SKonstantin Belousov 	ksi.ksi_uid = proc->p_ucred->cr_ruid;
588aa8b2011SKonstantin Belousov 
589ad6eec7bSJohn Baldwin 	error = pksignal(p, ksi.ksi_signo, &ksi);
590aa8b2011SKonstantin Belousov 
591aa8b2011SKonstantin Belousov out:
592aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
593aa8b2011SKonstantin Belousov 	return (error);
594aa8b2011SKonstantin Belousov }
595aa8b2011SKonstantin Belousov 
5969b44bfc5SAlexander Leidinger int
5979b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5989b44bfc5SAlexander Leidinger {
5999b44bfc5SAlexander Leidinger 
6009b44bfc5SAlexander Leidinger #ifdef DEBUG
6019b44bfc5SAlexander Leidinger 	if (ldebug(tgkill))
6029b44bfc5SAlexander Leidinger 		printf(ARGS(tgkill, "%d, %d, %d"), args->tgid, args->pid, args->sig);
6039b44bfc5SAlexander Leidinger #endif
604aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
605aa8b2011SKonstantin Belousov 		return (EINVAL);
6069b44bfc5SAlexander Leidinger 
607aa8b2011SKonstantin Belousov 	return (linux_do_tkill(td, args->tgid, args->pid, args->sig));
6089b44bfc5SAlexander Leidinger }
6099b44bfc5SAlexander Leidinger 
6109b44bfc5SAlexander Leidinger int
6119b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
6129b44bfc5SAlexander Leidinger {
6139b44bfc5SAlexander Leidinger #ifdef DEBUG
6149b44bfc5SAlexander Leidinger 	if (ldebug(tkill))
6159b44bfc5SAlexander Leidinger 		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
6169b44bfc5SAlexander Leidinger #endif
617aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
618aa8b2011SKonstantin Belousov 		return (EINVAL);
6199b44bfc5SAlexander Leidinger 
620aa8b2011SKonstantin Belousov 	return (linux_do_tkill(td, 0, args->tid, args->sig));
621aa8b2011SKonstantin Belousov }
622aa8b2011SKonstantin Belousov 
623aa8b2011SKonstantin Belousov void
624aa8b2011SKonstantin Belousov ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
625aa8b2011SKonstantin Belousov {
626aa8b2011SKonstantin Belousov 
627aa8b2011SKonstantin Belousov 	lsi->lsi_signo = sig;
628aa8b2011SKonstantin Belousov 	lsi->lsi_code = ksi->ksi_code;
629aa8b2011SKonstantin Belousov 
630aa8b2011SKonstantin Belousov 	switch (sig) {
631aa8b2011SKonstantin Belousov 	case LINUX_SIGPOLL:
632aa8b2011SKonstantin Belousov 		/* XXX si_fd? */
633aa8b2011SKonstantin Belousov 		lsi->lsi_band = ksi->ksi_band;
634aa8b2011SKonstantin Belousov 		break;
635aa8b2011SKonstantin Belousov 	case LINUX_SIGCHLD:
636aa8b2011SKonstantin Belousov 		lsi->lsi_pid = ksi->ksi_pid;
637aa8b2011SKonstantin Belousov 		lsi->lsi_uid = ksi->ksi_uid;
638aa8b2011SKonstantin Belousov 		lsi->lsi_status = ksi->ksi_status;
639aa8b2011SKonstantin Belousov 		break;
640aa8b2011SKonstantin Belousov 	case LINUX_SIGBUS:
641aa8b2011SKonstantin Belousov 	case LINUX_SIGILL:
642aa8b2011SKonstantin Belousov 	case LINUX_SIGFPE:
643aa8b2011SKonstantin Belousov 	case LINUX_SIGSEGV:
644aa8b2011SKonstantin Belousov 		lsi->lsi_addr = PTROUT(ksi->ksi_addr);
645aa8b2011SKonstantin Belousov 		break;
646aa8b2011SKonstantin Belousov 	default:
647aa8b2011SKonstantin Belousov 		/* XXX SI_TIMER etc... */
648aa8b2011SKonstantin Belousov 		lsi->lsi_pid = ksi->ksi_pid;
649aa8b2011SKonstantin Belousov 		lsi->lsi_uid = ksi->ksi_uid;
650aa8b2011SKonstantin Belousov 		break;
651aa8b2011SKonstantin Belousov 	}
65209d6cb0aSDmitry Chagin 	if (sig >= LINUX_SIGRTMIN) {
65309d6cb0aSDmitry Chagin 		lsi->lsi_int = ksi->ksi_info.si_value.sival_int;
65409d6cb0aSDmitry Chagin 		lsi->lsi_ptr = PTROUT(ksi->ksi_info.si_value.sival_ptr);
65509d6cb0aSDmitry Chagin 	}
6569b44bfc5SAlexander Leidinger }
657