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
2993107373SDmitry Chagin #include "opt_ktrace.h"
3093107373SDmitry Chagin
31c21dee17SSøren Schmidt #include <sys/param.h>
3230c6d982SEdward Tomasz Napierala #include <sys/ktr.h>
33fb919e4dSMark Murray #include <sys/lock.h>
34fb919e4dSMark Murray #include <sys/mutex.h>
35c21dee17SSøren Schmidt #include <sys/proc.h>
36c21dee17SSøren Schmidt #include <sys/signalvar.h>
37d8e53d94SDmitry Chagin #include <sys/sx.h>
38206a5d3aSIan Dowse #include <sys/syscallsubr.h>
39fb919e4dSMark Murray #include <sys/sysproto.h>
4093107373SDmitry Chagin #ifdef KTRACE
4193107373SDmitry Chagin #include <sys/ktrace.h>
4293107373SDmitry Chagin #endif
43c21dee17SSøren Schmidt
44aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
45aa8b2011SKonstantin Belousov
461997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
474af27623STim J. Robbins #include <machine/../linux32/linux.h>
484af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
491997c537SDavid E. O'Brien #else
501997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
511997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
524af27623STim J. Robbins #endif
539c1045ffSDmitry Chagin #include <compat/linux/linux_mib.h>
54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
55c8a79231SDmitry Chagin #include <compat/linux/linux_time.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
606201a50dSDmitry Chagin static int linux_pksignal(struct thread *td, int pid, int sig,
6181338031SDmitry Chagin ksiginfo_t *ksi);
626201a50dSDmitry Chagin static int linux_psignal(struct thread *td, int pid, int sig);
636201a50dSDmitry Chagin static int linux_tdksignal(struct thread *td, lwpid_t tid,
646201a50dSDmitry Chagin int tgid, int sig, ksiginfo_t *ksi);
656201a50dSDmitry Chagin static int linux_tdsignal(struct thread *td, lwpid_t tid,
666201a50dSDmitry Chagin int tgid, int sig);
67a6f85b12SDmitry Chagin static void sicode_to_lsicode(int sig, int si_code, int *lsi_code);
68db4a1f33SDmitry Chagin static int linux_common_rt_sigtimedwait(struct thread *,
69db4a1f33SDmitry Chagin l_sigset_t *, struct timespec *, l_siginfo_t *,
70db4a1f33SDmitry Chagin l_size_t);
71fe4ed1e7SDmitry Chagin
72a1ebcbfbSPeter Wemm static void
linux_to_bsd_sigaction(l_sigaction_t * lsa,struct sigaction * bsa)735002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
74d66a5066SPeter Wemm {
75d5629eb2SEdward Tomasz Napierala unsigned long flags;
76956d3333SMarcel Moolenaar
77956d3333SMarcel Moolenaar linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
784af27623STim J. Robbins bsa->sa_handler = PTRIN(lsa->lsa_handler);
79d66a5066SPeter Wemm bsa->sa_flags = 0;
80d5629eb2SEdward Tomasz Napierala
81d5629eb2SEdward Tomasz Napierala flags = lsa->lsa_flags;
82d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
83d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_NOCLDSTOP;
84d66a5066SPeter Wemm bsa->sa_flags |= SA_NOCLDSTOP;
85d5629eb2SEdward Tomasz Napierala }
86d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
87d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_NOCLDWAIT;
8806ebbe77SMarcel Moolenaar bsa->sa_flags |= SA_NOCLDWAIT;
89d5629eb2SEdward Tomasz Napierala }
90d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
91d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_SIGINFO;
9206ebbe77SMarcel Moolenaar bsa->sa_flags |= SA_SIGINFO;
93d5629eb2SEdward Tomasz Napierala #ifdef notyet
94d5629eb2SEdward Tomasz Napierala /*
95d5629eb2SEdward Tomasz Napierala * XXX: We seem to be missing code to convert
96d5629eb2SEdward Tomasz Napierala * some of the fields in ucontext_t.
97d5629eb2SEdward Tomasz Napierala */
98d5629eb2SEdward Tomasz Napierala linux_msg(curthread,
99d5629eb2SEdward Tomasz Napierala "partially unsupported sigaction flag SA_SIGINFO");
100d5629eb2SEdward Tomasz Napierala #endif
101d5629eb2SEdward Tomasz Napierala }
102d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_RESTORER) {
103d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_RESTORER;
1043eaf271dSEdward Tomasz Napierala /*
1053eaf271dSEdward Tomasz Napierala * We ignore the lsa_restorer and always use our own signal
1063eaf271dSEdward Tomasz Napierala * trampoline instead. It looks like SA_RESTORER is obsolete
1073eaf271dSEdward Tomasz Napierala * in Linux too - it doesn't seem to be used at all on arm64.
1083eaf271dSEdward Tomasz Napierala * In any case: see Linux sigreturn(2).
1093eaf271dSEdward Tomasz Napierala */
110d5629eb2SEdward Tomasz Napierala }
111d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
112d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_ONSTACK;
113d66a5066SPeter Wemm bsa->sa_flags |= SA_ONSTACK;
114d5629eb2SEdward Tomasz Napierala }
115d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_RESTART) {
116d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_RESTART;
117d66a5066SPeter Wemm bsa->sa_flags |= SA_RESTART;
118d5629eb2SEdward Tomasz Napierala }
1199bc42c18SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
1209bc42c18SEdward Tomasz Napierala flags &= ~LINUX_SA_INTERRUPT;
1219bc42c18SEdward Tomasz Napierala /* Documented to be a "historical no-op". */
1229bc42c18SEdward Tomasz Napierala }
123d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
124d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_ONESHOT;
125d66a5066SPeter Wemm bsa->sa_flags |= SA_RESETHAND;
126d5629eb2SEdward Tomasz Napierala }
127d5629eb2SEdward Tomasz Napierala if (lsa->lsa_flags & LINUX_SA_NOMASK) {
128d5629eb2SEdward Tomasz Napierala flags &= ~LINUX_SA_NOMASK;
129d66a5066SPeter Wemm bsa->sa_flags |= SA_NODEFER;
130d66a5066SPeter Wemm }
131d66a5066SPeter Wemm
132d5629eb2SEdward Tomasz Napierala if (flags != 0)
133d5629eb2SEdward Tomasz Napierala linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
134d5629eb2SEdward Tomasz Napierala }
135d5629eb2SEdward Tomasz Napierala
136a1ebcbfbSPeter Wemm static void
bsd_to_linux_sigaction(struct sigaction * bsa,l_sigaction_t * lsa)1375002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
138d66a5066SPeter Wemm {
139956d3333SMarcel Moolenaar
140956d3333SMarcel Moolenaar bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1411997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1424af27623STim J. Robbins lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1434af27623STim J. Robbins #else
1448f437f44SMartin Cracauer lsa->lsa_handler = bsa->sa_handler;
1454af27623STim J. Robbins #endif
1464af27623STim J. Robbins lsa->lsa_restorer = 0; /* unsupported */
1478f437f44SMartin Cracauer lsa->lsa_flags = 0;
148d66a5066SPeter Wemm if (bsa->sa_flags & SA_NOCLDSTOP)
1498f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
15006ebbe77SMarcel Moolenaar if (bsa->sa_flags & SA_NOCLDWAIT)
15106ebbe77SMarcel Moolenaar lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
15206ebbe77SMarcel Moolenaar if (bsa->sa_flags & SA_SIGINFO)
15306ebbe77SMarcel Moolenaar lsa->lsa_flags |= LINUX_SA_SIGINFO;
154d66a5066SPeter Wemm if (bsa->sa_flags & SA_ONSTACK)
1558f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_ONSTACK;
156d66a5066SPeter Wemm if (bsa->sa_flags & SA_RESTART)
1578f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_RESTART;
158d66a5066SPeter Wemm if (bsa->sa_flags & SA_RESETHAND)
1598f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_ONESHOT;
160d66a5066SPeter Wemm if (bsa->sa_flags & SA_NODEFER)
1618f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_NOMASK;
162d66a5066SPeter Wemm }
163c21dee17SSøren Schmidt
164ba9ef45bSMarcel Moolenaar int
linux_do_sigaction(struct thread * td,int linux_sig,l_sigaction_t * linux_nsa,l_sigaction_t * linux_osa)165b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1665002a60fSMarcel Moolenaar l_sigaction_t *linux_osa)
16706ebbe77SMarcel Moolenaar {
168206a5d3aSIan Dowse struct sigaction act, oact, *nsa, *osa;
169206a5d3aSIan Dowse int error, sig;
17006ebbe77SMarcel Moolenaar
171687c23beSAlexander Leidinger if (!LINUX_SIG_VALID(linux_sig))
172956d3333SMarcel Moolenaar return (EINVAL);
173*227d01c1SDmitry Chagin sig = linux_to_bsd_signal(linux_sig);
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);
17993107373SDmitry Chagin #ifdef KTRACE
18093107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
18193107373SDmitry Chagin linux_ktrsigset(&linux_nsa->lsa_mask,
18293107373SDmitry Chagin sizeof(linux_nsa->lsa_mask));
18393107373SDmitry Chagin #endif
184*227d01c1SDmitry Chagin if ((sig == SIGKILL || sig == SIGSTOP) &&
185*227d01c1SDmitry Chagin nsa->sa_handler == SIG_DFL)
186*227d01c1SDmitry Chagin return (EINVAL);
187206a5d3aSIan Dowse } else
18806ebbe77SMarcel Moolenaar nsa = NULL;
189956d3333SMarcel Moolenaar
190206a5d3aSIan Dowse error = kern_sigaction(td, sig, nsa, osa, 0);
19155731437SDmitry Chagin if (error != 0)
192956d3333SMarcel Moolenaar return (error);
19306ebbe77SMarcel Moolenaar
19493107373SDmitry Chagin if (linux_osa != NULL) {
195ec99e322SMarcel Moolenaar bsd_to_linux_sigaction(osa, linux_osa);
19693107373SDmitry Chagin #ifdef KTRACE
19793107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
19893107373SDmitry Chagin linux_ktrsigset(&linux_osa->lsa_mask,
19993107373SDmitry Chagin sizeof(linux_osa->lsa_mask));
20093107373SDmitry Chagin #endif
20193107373SDmitry Chagin }
202956d3333SMarcel Moolenaar return (0);
20306ebbe77SMarcel Moolenaar }
20406ebbe77SMarcel Moolenaar
20530c6d982SEdward Tomasz Napierala int
linux_sigaltstack(struct thread * td,struct linux_sigaltstack_args * uap)20630c6d982SEdward Tomasz Napierala linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
20730c6d982SEdward Tomasz Napierala {
20830c6d982SEdward Tomasz Napierala stack_t ss, oss;
20930c6d982SEdward Tomasz Napierala l_stack_t lss;
21030c6d982SEdward Tomasz Napierala int error;
21130c6d982SEdward Tomasz Napierala
21230c6d982SEdward Tomasz Napierala memset(&lss, 0, sizeof(lss));
21330c6d982SEdward Tomasz Napierala LINUX_CTR2(sigaltstack, "%p, %p", uap->uss, uap->uoss);
21430c6d982SEdward Tomasz Napierala
21530c6d982SEdward Tomasz Napierala if (uap->uss != NULL) {
2162722e515SDmitry Chagin error = copyin(uap->uss, &lss, sizeof(lss));
21730c6d982SEdward Tomasz Napierala if (error != 0)
21830c6d982SEdward Tomasz Napierala return (error);
21930c6d982SEdward Tomasz Napierala
22030c6d982SEdward Tomasz Napierala ss.ss_sp = PTRIN(lss.ss_sp);
22130c6d982SEdward Tomasz Napierala ss.ss_size = lss.ss_size;
22230c6d982SEdward Tomasz Napierala ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
22330c6d982SEdward Tomasz Napierala }
22430c6d982SEdward Tomasz Napierala error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL,
22530c6d982SEdward Tomasz Napierala (uap->uoss != NULL) ? &oss : NULL);
22630c6d982SEdward Tomasz Napierala if (error == 0 && uap->uoss != NULL) {
22730c6d982SEdward Tomasz Napierala lss.ss_sp = PTROUT(oss.ss_sp);
22830c6d982SEdward Tomasz Napierala lss.ss_size = oss.ss_size;
22930c6d982SEdward Tomasz Napierala lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
2302722e515SDmitry Chagin error = copyout(&lss, uap->uoss, sizeof(lss));
23130c6d982SEdward Tomasz Napierala }
23230c6d982SEdward Tomasz Napierala
23330c6d982SEdward Tomasz Napierala return (error);
23430c6d982SEdward Tomasz Napierala }
23530c6d982SEdward Tomasz Napierala
2367f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
237c21dee17SSøren Schmidt int
linux_signal(struct thread * td,struct linux_signal_args * args)238b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
239d66a5066SPeter Wemm {
2405002a60fSMarcel Moolenaar l_sigaction_t nsa, osa;
241d66a5066SPeter Wemm int error;
242d66a5066SPeter Wemm
24306ebbe77SMarcel Moolenaar nsa.lsa_handler = args->handler;
24406ebbe77SMarcel Moolenaar nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
245956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(nsa.lsa_mask);
246d66a5066SPeter Wemm
247b40ce416SJulian Elischer error = linux_do_sigaction(td, args->sig, &nsa, &osa);
2484af27623STim J. Robbins td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
249d66a5066SPeter Wemm
250956d3333SMarcel Moolenaar return (error);
251d66a5066SPeter Wemm }
2527f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
253d66a5066SPeter Wemm
254c21dee17SSøren Schmidt int
linux_rt_sigaction(struct thread * td,struct linux_rt_sigaction_args * args)255b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
256c21dee17SSøren Schmidt {
2575002a60fSMarcel Moolenaar l_sigaction_t nsa, osa;
25806ebbe77SMarcel Moolenaar int error;
259c21dee17SSøren Schmidt
2605002a60fSMarcel Moolenaar if (args->sigsetsize != sizeof(l_sigset_t))
261956d3333SMarcel Moolenaar return (EINVAL);
26206ebbe77SMarcel Moolenaar
263956d3333SMarcel Moolenaar if (args->act != NULL) {
2642722e515SDmitry Chagin error = copyin(args->act, &nsa, sizeof(nsa));
26555731437SDmitry Chagin if (error != 0)
266956d3333SMarcel Moolenaar return (error);
26706ebbe77SMarcel Moolenaar }
26806ebbe77SMarcel Moolenaar
269b40ce416SJulian Elischer error = linux_do_sigaction(td, args->sig,
27006ebbe77SMarcel Moolenaar args->act ? &nsa : NULL,
27106ebbe77SMarcel Moolenaar args->oact ? &osa : NULL);
27206ebbe77SMarcel Moolenaar
27355731437SDmitry Chagin if (args->oact != NULL && error == 0)
2742722e515SDmitry Chagin error = copyout(&osa, args->oact, sizeof(osa));
27506ebbe77SMarcel Moolenaar
276956d3333SMarcel Moolenaar return (error);
27706ebbe77SMarcel Moolenaar }
27806ebbe77SMarcel Moolenaar
27906ebbe77SMarcel Moolenaar static int
linux_do_sigprocmask(struct thread * td,int how,sigset_t * new,l_sigset_t * old)2805e872c27SDmitry Chagin linux_do_sigprocmask(struct thread *td, int how, sigset_t *new,
2815002a60fSMarcel Moolenaar l_sigset_t *old)
28206ebbe77SMarcel Moolenaar {
2835e872c27SDmitry Chagin sigset_t omask;
284216af822SJohn Baldwin int error;
28506ebbe77SMarcel Moolenaar
286b40ce416SJulian Elischer td->td_retval[0] = 0;
287d66a5066SPeter Wemm
28819dde5cdSJohn Baldwin switch (how) {
28919dde5cdSJohn Baldwin case LINUX_SIG_BLOCK:
29019dde5cdSJohn Baldwin how = SIG_BLOCK;
29119dde5cdSJohn Baldwin break;
29219dde5cdSJohn Baldwin case LINUX_SIG_UNBLOCK:
29319dde5cdSJohn Baldwin how = SIG_UNBLOCK;
29419dde5cdSJohn Baldwin break;
29519dde5cdSJohn Baldwin case LINUX_SIG_SETMASK:
29619dde5cdSJohn Baldwin how = SIG_SETMASK;
29719dde5cdSJohn Baldwin break;
29819dde5cdSJohn Baldwin default:
29919dde5cdSJohn Baldwin return (EINVAL);
30019dde5cdSJohn Baldwin }
3015e872c27SDmitry Chagin error = kern_sigprocmask(td, how, new, &omask, 0);
3022f7ed219SJohn Baldwin if (error == 0 && old != NULL)
303fe8cdcaeSJohn Baldwin bsd_to_linux_sigset(&omask, old);
30406ebbe77SMarcel Moolenaar
305956d3333SMarcel Moolenaar return (error);
30606ebbe77SMarcel Moolenaar }
30706ebbe77SMarcel Moolenaar
3087f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
30906ebbe77SMarcel Moolenaar int
linux_sigprocmask(struct thread * td,struct linux_sigprocmask_args * args)310b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
31106ebbe77SMarcel Moolenaar {
3125002a60fSMarcel Moolenaar l_osigset_t mask;
3135e872c27SDmitry Chagin l_sigset_t lset, oset;
3145e872c27SDmitry Chagin sigset_t set;
31506ebbe77SMarcel Moolenaar int error;
31606ebbe77SMarcel Moolenaar
31706ebbe77SMarcel Moolenaar if (args->mask != NULL) {
3182722e515SDmitry Chagin error = copyin(args->mask, &mask, sizeof(mask));
31955731437SDmitry Chagin if (error != 0)
320956d3333SMarcel Moolenaar return (error);
3215e872c27SDmitry Chagin LINUX_SIGEMPTYSET(lset);
3225e872c27SDmitry Chagin lset.__mask = mask;
32393107373SDmitry Chagin #ifdef KTRACE
32493107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
32593107373SDmitry Chagin linux_ktrsigset(&lset, sizeof(lset));
32693107373SDmitry Chagin #endif
3275e872c27SDmitry Chagin linux_to_bsd_sigset(&lset, &set);
32806ebbe77SMarcel Moolenaar }
32906ebbe77SMarcel Moolenaar
330b40ce416SJulian Elischer error = linux_do_sigprocmask(td, args->how,
331956d3333SMarcel Moolenaar args->mask ? &set : NULL,
332956d3333SMarcel Moolenaar args->omask ? &oset : NULL);
33306ebbe77SMarcel Moolenaar
33455731437SDmitry Chagin if (args->omask != NULL && error == 0) {
33593107373SDmitry Chagin #ifdef KTRACE
33693107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
33793107373SDmitry Chagin linux_ktrsigset(&oset, sizeof(oset));
33893107373SDmitry Chagin #endif
3394ab7403bSDmitry Chagin mask = oset.__mask;
3402722e515SDmitry Chagin error = copyout(&mask, args->omask, sizeof(mask));
34106ebbe77SMarcel Moolenaar }
34206ebbe77SMarcel Moolenaar
343956d3333SMarcel Moolenaar return (error);
34406ebbe77SMarcel Moolenaar }
3457f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
34606ebbe77SMarcel Moolenaar
34706ebbe77SMarcel Moolenaar int
linux_rt_sigprocmask(struct thread * td,struct linux_rt_sigprocmask_args * args)348b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
34906ebbe77SMarcel Moolenaar {
3505e872c27SDmitry Chagin l_sigset_t oset;
3515e872c27SDmitry Chagin sigset_t set, *pset;
35206ebbe77SMarcel Moolenaar int error;
35306ebbe77SMarcel Moolenaar
35493107373SDmitry Chagin error = linux_copyin_sigset(td, args->mask, args->sigsetsize,
3555e872c27SDmitry Chagin &set, &pset);
3565e872c27SDmitry Chagin if (error != 0)
357340f4a8dSEd Maste return (EINVAL);
35806ebbe77SMarcel Moolenaar
3595e872c27SDmitry Chagin error = linux_do_sigprocmask(td, args->how, pset,
360956d3333SMarcel Moolenaar args->omask ? &oset : NULL);
36106ebbe77SMarcel Moolenaar
36293107373SDmitry Chagin if (args->omask != NULL && error == 0) {
36393107373SDmitry Chagin #ifdef KTRACE
36493107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
36593107373SDmitry Chagin linux_ktrsigset(&oset, sizeof(oset));
36693107373SDmitry Chagin #endif
3672722e515SDmitry Chagin error = copyout(&oset, args->omask, sizeof(oset));
36893107373SDmitry Chagin }
36906ebbe77SMarcel Moolenaar
370956d3333SMarcel Moolenaar return (error);
371c21dee17SSøren Schmidt }
372c21dee17SSøren Schmidt
3737f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
374c21dee17SSøren Schmidt int
linux_sgetmask(struct thread * td,struct linux_sgetmask_args * args)375b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
376c21dee17SSøren Schmidt {
377b40ce416SJulian Elischer struct proc *p = td->td_proc;
3785002a60fSMarcel Moolenaar l_sigset_t mask;
379956d3333SMarcel Moolenaar
380216af822SJohn Baldwin PROC_LOCK(p);
3814093529dSJeff Roberson bsd_to_linux_sigset(&td->td_sigmask, &mask);
382216af822SJohn Baldwin PROC_UNLOCK(p);
3834ab7403bSDmitry Chagin td->td_retval[0] = mask.__mask;
38493107373SDmitry Chagin #ifdef KTRACE
38593107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
38693107373SDmitry Chagin linux_ktrsigset(&mask, sizeof(mask));
38793107373SDmitry Chagin #endif
388956d3333SMarcel Moolenaar return (0);
389c21dee17SSøren Schmidt }
390c21dee17SSøren Schmidt
391c21dee17SSøren Schmidt int
linux_ssetmask(struct thread * td,struct linux_ssetmask_args * args)392b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
393c21dee17SSøren Schmidt {
394b40ce416SJulian Elischer struct proc *p = td->td_proc;
3955002a60fSMarcel Moolenaar l_sigset_t lset;
396956d3333SMarcel Moolenaar sigset_t bset;
397c21dee17SSøren Schmidt
398216af822SJohn Baldwin PROC_LOCK(p);
3994093529dSJeff Roberson bsd_to_linux_sigset(&td->td_sigmask, &lset);
4004ab7403bSDmitry Chagin td->td_retval[0] = lset.__mask;
401956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(lset);
4024ab7403bSDmitry Chagin lset.__mask = args->mask;
403956d3333SMarcel Moolenaar linux_to_bsd_sigset(&lset, &bset);
40493107373SDmitry Chagin #ifdef KTRACE
40593107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
40693107373SDmitry Chagin linux_ktrsigset(&lset, sizeof(lset));
40793107373SDmitry Chagin #endif
4084093529dSJeff Roberson td->td_sigmask = bset;
4094093529dSJeff Roberson SIG_CANTMASK(td->td_sigmask);
4104093529dSJeff Roberson signotify(td);
411216af822SJohn Baldwin PROC_UNLOCK(p);
412956d3333SMarcel Moolenaar return (0);
413c21dee17SSøren Schmidt }
414c21dee17SSøren Schmidt
415c21dee17SSøren Schmidt int
linux_sigpending(struct thread * td,struct linux_sigpending_args * args)416b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
417c21dee17SSøren Schmidt {
418b40ce416SJulian Elischer struct proc *p = td->td_proc;
419956d3333SMarcel Moolenaar sigset_t bset;
4205002a60fSMarcel Moolenaar l_sigset_t lset;
4215002a60fSMarcel Moolenaar l_osigset_t mask;
422c21dee17SSøren Schmidt
423216af822SJohn Baldwin PROC_LOCK(p);
4241d9c5696SJuli Mallett bset = p->p_siglist;
4254093529dSJeff Roberson SIGSETOR(bset, td->td_siglist);
4264093529dSJeff Roberson SIGSETAND(bset, td->td_sigmask);
427216af822SJohn Baldwin PROC_UNLOCK(p);
4289d8643ecSJohn Baldwin bsd_to_linux_sigset(&bset, &lset);
42993107373SDmitry Chagin #ifdef KTRACE
43093107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
43193107373SDmitry Chagin linux_ktrsigset(&lset, sizeof(lset));
43293107373SDmitry Chagin #endif
4334ab7403bSDmitry Chagin mask = lset.__mask;
434956d3333SMarcel Moolenaar return (copyout(&mask, args->mask, sizeof(mask)));
435c21dee17SSøren Schmidt }
4367f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
43717138b61SAlexander Leidinger
43817138b61SAlexander Leidinger /*
43917138b61SAlexander Leidinger * MPSAFE
44017138b61SAlexander Leidinger */
44117138b61SAlexander Leidinger int
linux_rt_sigpending(struct thread * td,struct linux_rt_sigpending_args * args)44217138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
44317138b61SAlexander Leidinger {
44417138b61SAlexander Leidinger struct proc *p = td->td_proc;
44517138b61SAlexander Leidinger sigset_t bset;
44617138b61SAlexander Leidinger l_sigset_t lset;
44717138b61SAlexander Leidinger
44817138b61SAlexander Leidinger if (args->sigsetsize > sizeof(lset))
449340f4a8dSEd Maste return (EINVAL);
45017138b61SAlexander Leidinger /* NOT REACHED */
45117138b61SAlexander Leidinger
45217138b61SAlexander Leidinger PROC_LOCK(p);
45317138b61SAlexander Leidinger bset = p->p_siglist;
45417138b61SAlexander Leidinger SIGSETOR(bset, td->td_siglist);
45517138b61SAlexander Leidinger SIGSETAND(bset, td->td_sigmask);
45617138b61SAlexander Leidinger PROC_UNLOCK(p);
45717138b61SAlexander Leidinger bsd_to_linux_sigset(&bset, &lset);
45893107373SDmitry Chagin #ifdef KTRACE
45993107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
46093107373SDmitry Chagin linux_ktrsigset(&lset, sizeof(lset));
46193107373SDmitry Chagin #endif
46217138b61SAlexander Leidinger return (copyout(&lset, args->set, args->sigsetsize));
46317138b61SAlexander Leidinger }
464c21dee17SSøren Schmidt
465c9447c75SAlexander Leidinger int
linux_rt_sigtimedwait(struct thread * td,struct linux_rt_sigtimedwait_args * args)466c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
467c9447c75SAlexander Leidinger struct linux_rt_sigtimedwait_args *args)
468c9447c75SAlexander Leidinger {
469c9447c75SAlexander Leidinger struct timespec ts, *tsa;
470db4a1f33SDmitry Chagin int error;
471c9447c75SAlexander Leidinger
472c9447c75SAlexander Leidinger if (args->timeout) {
473707e567aSDmitry Chagin error = linux_get_timespec(&ts, args->timeout);
4740f8dab45SDmitry Chagin if (error != 0)
4750f8dab45SDmitry Chagin return (error);
476c9447c75SAlexander Leidinger tsa = &ts;
4770f8dab45SDmitry Chagin } else
4780f8dab45SDmitry Chagin tsa = NULL;
4790f8dab45SDmitry Chagin
480db4a1f33SDmitry Chagin return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
481db4a1f33SDmitry Chagin args->ptr, args->sigsetsize));
482db4a1f33SDmitry Chagin }
483db4a1f33SDmitry Chagin
484db4a1f33SDmitry Chagin static int
linux_common_rt_sigtimedwait(struct thread * td,l_sigset_t * mask,struct timespec * tsa,l_siginfo_t * ptr,l_size_t sigsetsize)485db4a1f33SDmitry Chagin linux_common_rt_sigtimedwait(struct thread *td, l_sigset_t *mask,
486db4a1f33SDmitry Chagin struct timespec *tsa, l_siginfo_t *ptr, l_size_t sigsetsize)
487db4a1f33SDmitry Chagin {
488db4a1f33SDmitry Chagin int error, sig;
489db4a1f33SDmitry Chagin sigset_t bset;
490db4a1f33SDmitry Chagin l_siginfo_t lsi;
491db4a1f33SDmitry Chagin ksiginfo_t ksi;
492db4a1f33SDmitry Chagin
49393107373SDmitry Chagin error = linux_copyin_sigset(td, mask, sigsetsize, &bset, NULL);
4943923e632SDmitry Chagin if (error != 0)
495db4a1f33SDmitry Chagin return (error);
496db4a1f33SDmitry Chagin
497db4a1f33SDmitry Chagin ksiginfo_init(&ksi);
498f4e80108SDmitry Chagin error = kern_sigtimedwait(td, bset, &ksi, tsa);
49955731437SDmitry Chagin if (error != 0)
500c9447c75SAlexander Leidinger return (error);
501c9447c75SAlexander Leidinger
502f4e80108SDmitry Chagin sig = bsd_to_linux_signal(ksi.ksi_signo);
503f3481dd9SDmitry Chagin
504db4a1f33SDmitry Chagin if (ptr) {
505f4e80108SDmitry Chagin memset(&lsi, 0, sizeof(lsi));
506f4e80108SDmitry Chagin siginfo_to_lsiginfo(&ksi.ksi_info, &lsi, sig);
507db4a1f33SDmitry Chagin error = copyout(&lsi, ptr, sizeof(lsi));
508c9447c75SAlexander Leidinger }
509f3481dd9SDmitry Chagin if (error == 0)
510f3481dd9SDmitry Chagin td->td_retval[0] = sig;
511c9447c75SAlexander Leidinger
512c9447c75SAlexander Leidinger return (error);
513c9447c75SAlexander Leidinger }
514c9447c75SAlexander Leidinger
515db4a1f33SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
516db4a1f33SDmitry Chagin int
linux_rt_sigtimedwait_time64(struct thread * td,struct linux_rt_sigtimedwait_time64_args * args)517db4a1f33SDmitry Chagin linux_rt_sigtimedwait_time64(struct thread *td,
518db4a1f33SDmitry Chagin struct linux_rt_sigtimedwait_time64_args *args)
519db4a1f33SDmitry Chagin {
520db4a1f33SDmitry Chagin struct timespec ts, *tsa;
521db4a1f33SDmitry Chagin int error;
522db4a1f33SDmitry Chagin
523db4a1f33SDmitry Chagin if (args->timeout) {
524707e567aSDmitry Chagin error = linux_get_timespec64(&ts, args->timeout);
525db4a1f33SDmitry Chagin if (error != 0)
526db4a1f33SDmitry Chagin return (error);
527db4a1f33SDmitry Chagin tsa = &ts;
528db4a1f33SDmitry Chagin } else
529db4a1f33SDmitry Chagin tsa = NULL;
530db4a1f33SDmitry Chagin
531db4a1f33SDmitry Chagin return (linux_common_rt_sigtimedwait(td, args->mask, tsa,
532db4a1f33SDmitry Chagin args->ptr, args->sigsetsize));
533db4a1f33SDmitry Chagin }
534db4a1f33SDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
535db4a1f33SDmitry Chagin
536c21dee17SSøren Schmidt int
linux_kill(struct thread * td,struct linux_kill_args * args)537b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
538c21dee17SSøren Schmidt {
5396201a50dSDmitry Chagin int sig;
540c21dee17SSøren Schmidt
541956d3333SMarcel Moolenaar /*
542956d3333SMarcel Moolenaar * Allow signal 0 as a means to check for privileges
543956d3333SMarcel Moolenaar */
54464742216SAlexander Leidinger if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5459a6a64d3SDmitry Chagin return (EINVAL);
546956d3333SMarcel Moolenaar
5474ab7403bSDmitry Chagin if (args->signum > 0)
5486201a50dSDmitry Chagin sig = linux_to_bsd_signal(args->signum);
549956d3333SMarcel Moolenaar else
5506201a50dSDmitry Chagin sig = 0;
551956d3333SMarcel Moolenaar
5526201a50dSDmitry Chagin if (args->pid > PID_MAX)
5536201a50dSDmitry Chagin return (linux_psignal(td, args->pid, sig));
5546201a50dSDmitry Chagin else
5556201a50dSDmitry Chagin return (kern_kill(td, args->pid, sig));
556aa8b2011SKonstantin Belousov }
557aa8b2011SKonstantin Belousov
5589b44bfc5SAlexander Leidinger int
linux_tgkill(struct thread * td,struct linux_tgkill_args * args)5599b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5609b44bfc5SAlexander Leidinger {
56181338031SDmitry Chagin int sig;
5629b44bfc5SAlexander Leidinger
563aa8b2011SKonstantin Belousov if (args->pid <= 0 || args->tgid <=0)
564aa8b2011SKonstantin Belousov return (EINVAL);
5659b44bfc5SAlexander Leidinger
56681338031SDmitry Chagin /*
56781338031SDmitry Chagin * Allow signal 0 as a means to check for privileges
56881338031SDmitry Chagin */
56981338031SDmitry Chagin if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
57081338031SDmitry Chagin return (EINVAL);
57181338031SDmitry Chagin
5724ab7403bSDmitry Chagin if (args->sig > 0)
5734ab7403bSDmitry Chagin sig = linux_to_bsd_signal(args->sig);
57481338031SDmitry Chagin else
5754ab7403bSDmitry Chagin sig = 0;
57681338031SDmitry Chagin
5776201a50dSDmitry Chagin return (linux_tdsignal(td, args->pid, args->tgid, sig));
5789b44bfc5SAlexander Leidinger }
5799b44bfc5SAlexander Leidinger
58081338031SDmitry Chagin /*
58181338031SDmitry Chagin * Deprecated since 2.5.75. Replaced by tgkill().
58281338031SDmitry Chagin */
5839b44bfc5SAlexander Leidinger int
linux_tkill(struct thread * td,struct linux_tkill_args * args)5849b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
5859b44bfc5SAlexander Leidinger {
58681338031SDmitry Chagin int sig;
58781338031SDmitry Chagin
588aa8b2011SKonstantin Belousov if (args->tid <= 0)
589aa8b2011SKonstantin Belousov return (EINVAL);
5909b44bfc5SAlexander Leidinger
59181338031SDmitry Chagin if (!LINUX_SIG_VALID(args->sig))
59281338031SDmitry Chagin return (EINVAL);
59381338031SDmitry Chagin
5944ab7403bSDmitry Chagin sig = linux_to_bsd_signal(args->sig);
59581338031SDmitry Chagin
5966201a50dSDmitry Chagin return (linux_tdsignal(td, args->tid, -1, sig));
597aa8b2011SKonstantin Belousov }
598aa8b2011SKonstantin Belousov
599a6f85b12SDmitry Chagin static int
sigfpe_sicode2lsicode(int si_code)600a6f85b12SDmitry Chagin sigfpe_sicode2lsicode(int si_code)
601a6f85b12SDmitry Chagin {
602a6f85b12SDmitry Chagin
603a6f85b12SDmitry Chagin switch (si_code) {
604a6f85b12SDmitry Chagin case FPE_INTOVF:
605a6f85b12SDmitry Chagin return (LINUX_FPE_INTOVF);
606a6f85b12SDmitry Chagin case FPE_INTDIV:
607a6f85b12SDmitry Chagin return (LINUX_FPE_INTDIV);
608a6f85b12SDmitry Chagin case FPE_FLTIDO:
609a6f85b12SDmitry Chagin return (LINUX_FPE_FLTUNK);
610a6f85b12SDmitry Chagin default:
611a6f85b12SDmitry Chagin return (si_code);
612a6f85b12SDmitry Chagin }
613a6f85b12SDmitry Chagin }
614a6f85b12SDmitry Chagin
615a6f85b12SDmitry Chagin static int
sigbus_sicode2lsicode(int si_code)616a6f85b12SDmitry Chagin sigbus_sicode2lsicode(int si_code)
617a6f85b12SDmitry Chagin {
618a6f85b12SDmitry Chagin
619a6f85b12SDmitry Chagin switch (si_code) {
620a6f85b12SDmitry Chagin case BUS_OOMERR:
621a6f85b12SDmitry Chagin return (LINUX_BUS_MCEERR_AR);
622a6f85b12SDmitry Chagin default:
623a6f85b12SDmitry Chagin return (si_code);
624a6f85b12SDmitry Chagin }
625a6f85b12SDmitry Chagin }
626a6f85b12SDmitry Chagin
627a6f85b12SDmitry Chagin static int
sigsegv_sicode2lsicode(int si_code)628a6f85b12SDmitry Chagin sigsegv_sicode2lsicode(int si_code)
629a6f85b12SDmitry Chagin {
630a6f85b12SDmitry Chagin
631a6f85b12SDmitry Chagin switch (si_code) {
632a6f85b12SDmitry Chagin case SEGV_PKUERR:
633a6f85b12SDmitry Chagin return (LINUX_SEGV_PKUERR);
634a6f85b12SDmitry Chagin default:
635a6f85b12SDmitry Chagin return (si_code);
636a6f85b12SDmitry Chagin }
637a6f85b12SDmitry Chagin }
638a6f85b12SDmitry Chagin
639a6f85b12SDmitry Chagin static int
sigtrap_sicode2lsicode(int si_code)640a6f85b12SDmitry Chagin sigtrap_sicode2lsicode(int si_code)
641a6f85b12SDmitry Chagin {
642a6f85b12SDmitry Chagin
643a6f85b12SDmitry Chagin switch (si_code) {
644a6f85b12SDmitry Chagin case TRAP_DTRACE:
645a6f85b12SDmitry Chagin return (LINUX_TRAP_TRACE);
646a6f85b12SDmitry Chagin case TRAP_CAP:
647a6f85b12SDmitry Chagin return (LINUX_TRAP_UNK);
648a6f85b12SDmitry Chagin default:
649a6f85b12SDmitry Chagin return (si_code);
650a6f85b12SDmitry Chagin }
651a6f85b12SDmitry Chagin }
652a6f85b12SDmitry Chagin
653fe4ed1e7SDmitry Chagin static void
sicode_to_lsicode(int sig,int si_code,int * lsi_code)654a6f85b12SDmitry Chagin sicode_to_lsicode(int sig, int si_code, int *lsi_code)
655fe4ed1e7SDmitry Chagin {
656fe4ed1e7SDmitry Chagin
657fe4ed1e7SDmitry Chagin switch (si_code) {
658fe4ed1e7SDmitry Chagin case SI_USER:
659fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_USER;
660fe4ed1e7SDmitry Chagin break;
661fe4ed1e7SDmitry Chagin case SI_KERNEL:
662fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_KERNEL;
663fe4ed1e7SDmitry Chagin break;
664fe4ed1e7SDmitry Chagin case SI_QUEUE:
665fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_QUEUE;
666fe4ed1e7SDmitry Chagin break;
667fe4ed1e7SDmitry Chagin case SI_TIMER:
668fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_TIMER;
669fe4ed1e7SDmitry Chagin break;
670fe4ed1e7SDmitry Chagin case SI_MESGQ:
671fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_MESGQ;
672fe4ed1e7SDmitry Chagin break;
673fe4ed1e7SDmitry Chagin case SI_ASYNCIO:
674fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_ASYNCIO;
675fe4ed1e7SDmitry Chagin break;
676fe4ed1e7SDmitry Chagin case SI_LWP:
677fe4ed1e7SDmitry Chagin *lsi_code = LINUX_SI_TKILL;
678fe4ed1e7SDmitry Chagin break;
679fe4ed1e7SDmitry Chagin default:
680a6f85b12SDmitry Chagin switch (sig) {
681a6f85b12SDmitry Chagin case LINUX_SIGFPE:
682a6f85b12SDmitry Chagin *lsi_code = sigfpe_sicode2lsicode(si_code);
683a6f85b12SDmitry Chagin break;
684a6f85b12SDmitry Chagin case LINUX_SIGBUS:
685a6f85b12SDmitry Chagin *lsi_code = sigbus_sicode2lsicode(si_code);
686a6f85b12SDmitry Chagin break;
687a6f85b12SDmitry Chagin case LINUX_SIGSEGV:
688a6f85b12SDmitry Chagin *lsi_code = sigsegv_sicode2lsicode(si_code);
689a6f85b12SDmitry Chagin break;
690a6f85b12SDmitry Chagin case LINUX_SIGTRAP:
691a6f85b12SDmitry Chagin *lsi_code = sigtrap_sicode2lsicode(si_code);
692a6f85b12SDmitry Chagin break;
693a6f85b12SDmitry Chagin default:
694fe4ed1e7SDmitry Chagin *lsi_code = si_code;
695fe4ed1e7SDmitry Chagin break;
696fe4ed1e7SDmitry Chagin }
697a6f85b12SDmitry Chagin break;
698a6f85b12SDmitry Chagin }
699fe4ed1e7SDmitry Chagin }
700fe4ed1e7SDmitry Chagin
701fe4ed1e7SDmitry Chagin void
siginfo_to_lsiginfo(const siginfo_t * si,l_siginfo_t * lsi,l_int sig)702fe4ed1e7SDmitry Chagin siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
703fe4ed1e7SDmitry Chagin {
704fe4ed1e7SDmitry Chagin
705d3d3b76cSGordon Bergling /* sig already converted */
706fe4ed1e7SDmitry Chagin lsi->lsi_signo = sig;
707a6f85b12SDmitry Chagin sicode_to_lsicode(sig, si->si_code, &lsi->lsi_code);
708fe4ed1e7SDmitry Chagin
709fe4ed1e7SDmitry Chagin switch (si->si_code) {
710fe4ed1e7SDmitry Chagin case SI_LWP:
711fe4ed1e7SDmitry Chagin lsi->lsi_pid = si->si_pid;
712fe4ed1e7SDmitry Chagin lsi->lsi_uid = si->si_uid;
713fe4ed1e7SDmitry Chagin break;
714fe4ed1e7SDmitry Chagin
715fe4ed1e7SDmitry Chagin case SI_TIMER:
716fe4ed1e7SDmitry Chagin lsi->lsi_int = si->si_value.sival_int;
717fe4ed1e7SDmitry Chagin lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
718fe4ed1e7SDmitry Chagin lsi->lsi_tid = si->si_timerid;
719fe4ed1e7SDmitry Chagin break;
720fe4ed1e7SDmitry Chagin
721fe4ed1e7SDmitry Chagin case SI_QUEUE:
722fe4ed1e7SDmitry Chagin lsi->lsi_pid = si->si_pid;
723fe4ed1e7SDmitry Chagin lsi->lsi_uid = si->si_uid;
724fe4ed1e7SDmitry Chagin lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
725fe4ed1e7SDmitry Chagin break;
726fe4ed1e7SDmitry Chagin
727fe4ed1e7SDmitry Chagin case SI_ASYNCIO:
728fe4ed1e7SDmitry Chagin lsi->lsi_int = si->si_value.sival_int;
729fe4ed1e7SDmitry Chagin lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
730fe4ed1e7SDmitry Chagin break;
731fe4ed1e7SDmitry Chagin
732fe4ed1e7SDmitry Chagin default:
733aa8b2011SKonstantin Belousov switch (sig) {
734aa8b2011SKonstantin Belousov case LINUX_SIGPOLL:
735aa8b2011SKonstantin Belousov /* XXX si_fd? */
736fe4ed1e7SDmitry Chagin lsi->lsi_band = si->si_band;
737aa8b2011SKonstantin Belousov break;
738fe4ed1e7SDmitry Chagin
739aa8b2011SKonstantin Belousov case LINUX_SIGCHLD:
740fe4ed1e7SDmitry Chagin lsi->lsi_errno = 0;
741fe4ed1e7SDmitry Chagin lsi->lsi_pid = si->si_pid;
742fe4ed1e7SDmitry Chagin lsi->lsi_uid = si->si_uid;
743fe4ed1e7SDmitry Chagin
744c8c93b15SEdward Tomasz Napierala if (si->si_code == CLD_STOPPED || si->si_code == CLD_KILLED)
7454ab7403bSDmitry Chagin lsi->lsi_status = bsd_to_linux_signal(si->si_status);
746fe4ed1e7SDmitry Chagin else if (si->si_code == CLD_CONTINUED)
7474ab7403bSDmitry Chagin lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
748fe4ed1e7SDmitry Chagin else
749fe4ed1e7SDmitry Chagin lsi->lsi_status = si->si_status;
750aa8b2011SKonstantin Belousov break;
751fe4ed1e7SDmitry Chagin
752aa8b2011SKonstantin Belousov case LINUX_SIGBUS:
753aa8b2011SKonstantin Belousov case LINUX_SIGILL:
754aa8b2011SKonstantin Belousov case LINUX_SIGFPE:
755aa8b2011SKonstantin Belousov case LINUX_SIGSEGV:
756fe4ed1e7SDmitry Chagin lsi->lsi_addr = PTROUT(si->si_addr);
757aa8b2011SKonstantin Belousov break;
758fe4ed1e7SDmitry Chagin
759aa8b2011SKonstantin Belousov default:
760fe4ed1e7SDmitry Chagin lsi->lsi_pid = si->si_pid;
761fe4ed1e7SDmitry Chagin lsi->lsi_uid = si->si_uid;
762fe4ed1e7SDmitry Chagin if (sig >= LINUX_SIGRTMIN) {
763fe4ed1e7SDmitry Chagin lsi->lsi_int = si->si_value.sival_int;
764fe4ed1e7SDmitry Chagin lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
765fe4ed1e7SDmitry Chagin }
766aa8b2011SKonstantin Belousov break;
767aa8b2011SKonstantin Belousov }
768fe4ed1e7SDmitry Chagin break;
76909d6cb0aSDmitry Chagin }
7709b44bfc5SAlexander Leidinger }
7717ac9766dSDmitry Chagin
772794328fbSDmitry Chagin static int
lsiginfo_to_siginfo(struct thread * td,const l_siginfo_t * lsi,siginfo_t * si,int sig)7739c1045ffSDmitry Chagin lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
7749c1045ffSDmitry Chagin siginfo_t *si, int sig)
7757ac9766dSDmitry Chagin {
7767ac9766dSDmitry Chagin
7779c1045ffSDmitry Chagin switch (lsi->lsi_code) {
7789c1045ffSDmitry Chagin case LINUX_SI_TKILL:
779e185d83fSDmitry Chagin if (linux_kernver(td) >= LINUX_KERNVER(2,6,39)) {
7809c1045ffSDmitry Chagin linux_msg(td, "SI_TKILL forbidden since 2.6.39");
7819c1045ffSDmitry Chagin return (EPERM);
7829c1045ffSDmitry Chagin }
7839c1045ffSDmitry Chagin si->si_code = SI_LWP;
7849c1045ffSDmitry Chagin case LINUX_SI_QUEUE:
7859c1045ffSDmitry Chagin si->si_code = SI_QUEUE;
7869c1045ffSDmitry Chagin break;
7879c1045ffSDmitry Chagin case LINUX_SI_TIMER:
7889c1045ffSDmitry Chagin si->si_code = SI_TIMER;
7899c1045ffSDmitry Chagin break;
7909c1045ffSDmitry Chagin case LINUX_SI_MESGQ:
7919c1045ffSDmitry Chagin si->si_code = SI_MESGQ;
7929c1045ffSDmitry Chagin break;
7939c1045ffSDmitry Chagin case LINUX_SI_ASYNCIO:
7949c1045ffSDmitry Chagin si->si_code = SI_ASYNCIO;
7959c1045ffSDmitry Chagin break;
7969c1045ffSDmitry Chagin default:
7979c1045ffSDmitry Chagin si->si_code = lsi->lsi_code;
7989c1045ffSDmitry Chagin break;
7999c1045ffSDmitry Chagin }
8009c1045ffSDmitry Chagin
8019c1045ffSDmitry Chagin si->si_signo = sig;
8029c1045ffSDmitry Chagin si->si_pid = td->td_proc->p_pid;
8039c1045ffSDmitry Chagin si->si_uid = td->td_ucred->cr_ruid;
8049c1045ffSDmitry Chagin si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
8059c1045ffSDmitry Chagin return (0);
8067ac9766dSDmitry Chagin }
8077ac9766dSDmitry Chagin
8087ac9766dSDmitry Chagin int
linux_rt_sigqueueinfo(struct thread * td,struct linux_rt_sigqueueinfo_args * args)8097ac9766dSDmitry Chagin linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
8107ac9766dSDmitry Chagin {
8117ac9766dSDmitry Chagin l_siginfo_t linfo;
8127ac9766dSDmitry Chagin ksiginfo_t ksi;
8137ac9766dSDmitry Chagin int error;
8147ac9766dSDmitry Chagin int sig;
8157ac9766dSDmitry Chagin
8167ac9766dSDmitry Chagin if (!LINUX_SIG_VALID(args->sig))
8177ac9766dSDmitry Chagin return (EINVAL);
8187ac9766dSDmitry Chagin
8197ac9766dSDmitry Chagin error = copyin(args->info, &linfo, sizeof(linfo));
8207ac9766dSDmitry Chagin if (error != 0)
8217ac9766dSDmitry Chagin return (error);
8227ac9766dSDmitry Chagin
8237ac9766dSDmitry Chagin if (linfo.lsi_code >= 0)
8249c1045ffSDmitry Chagin /* SI_USER, SI_KERNEL */
8257ac9766dSDmitry Chagin return (EPERM);
8267ac9766dSDmitry Chagin
8274ab7403bSDmitry Chagin sig = linux_to_bsd_signal(args->sig);
8289c1045ffSDmitry Chagin ksiginfo_init(&ksi);
8299c1045ffSDmitry Chagin error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
8309c1045ffSDmitry Chagin if (error != 0)
8319c1045ffSDmitry Chagin return (error);
8327ac9766dSDmitry Chagin
8336201a50dSDmitry Chagin return (linux_pksignal(td, args->pid, sig, &ksi));
8347ac9766dSDmitry Chagin }
835486a06bdSDmitry Chagin
836486a06bdSDmitry Chagin int
linux_rt_tgsigqueueinfo(struct thread * td,struct linux_rt_tgsigqueueinfo_args * args)837486a06bdSDmitry Chagin linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
838486a06bdSDmitry Chagin {
839486a06bdSDmitry Chagin l_siginfo_t linfo;
840486a06bdSDmitry Chagin ksiginfo_t ksi;
841486a06bdSDmitry Chagin int error;
842486a06bdSDmitry Chagin int sig;
843486a06bdSDmitry Chagin
844486a06bdSDmitry Chagin if (!LINUX_SIG_VALID(args->sig))
845486a06bdSDmitry Chagin return (EINVAL);
846486a06bdSDmitry Chagin
847486a06bdSDmitry Chagin error = copyin(args->uinfo, &linfo, sizeof(linfo));
848486a06bdSDmitry Chagin if (error != 0)
849486a06bdSDmitry Chagin return (error);
850486a06bdSDmitry Chagin
851486a06bdSDmitry Chagin if (linfo.lsi_code >= 0)
852486a06bdSDmitry Chagin return (EPERM);
853486a06bdSDmitry Chagin
8549c1045ffSDmitry Chagin sig = linux_to_bsd_signal(args->sig);
8559c1045ffSDmitry Chagin ksiginfo_init(&ksi);
8569c1045ffSDmitry Chagin error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
8579c1045ffSDmitry Chagin if (error != 0)
8589c1045ffSDmitry Chagin return (error);
8599c1045ffSDmitry Chagin
8606201a50dSDmitry Chagin return (linux_tdksignal(td, args->tid, args->tgid, sig, &ksi));
861486a06bdSDmitry Chagin }
86272f7ddb5SEdward Tomasz Napierala
86372f7ddb5SEdward Tomasz Napierala int
linux_rt_sigsuspend(struct thread * td,struct linux_rt_sigsuspend_args * uap)86472f7ddb5SEdward Tomasz Napierala linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
86572f7ddb5SEdward Tomasz Napierala {
86672f7ddb5SEdward Tomasz Napierala sigset_t sigmask;
86772f7ddb5SEdward Tomasz Napierala int error;
86872f7ddb5SEdward Tomasz Napierala
86993107373SDmitry Chagin error = linux_copyin_sigset(td, uap->newset, uap->sigsetsize,
8703923e632SDmitry Chagin &sigmask, NULL);
87172f7ddb5SEdward Tomasz Napierala if (error != 0)
87272f7ddb5SEdward Tomasz Napierala return (error);
87372f7ddb5SEdward Tomasz Napierala
87472f7ddb5SEdward Tomasz Napierala return (kern_sigsuspend(td, sigmask));
87572f7ddb5SEdward Tomasz Napierala }
8766201a50dSDmitry Chagin
8776201a50dSDmitry Chagin static int
linux_tdksignal(struct thread * td,lwpid_t tid,int tgid,int sig,ksiginfo_t * ksi)8786201a50dSDmitry Chagin linux_tdksignal(struct thread *td, lwpid_t tid, int tgid, int sig,
8796201a50dSDmitry Chagin ksiginfo_t *ksi)
8806201a50dSDmitry Chagin {
8816201a50dSDmitry Chagin struct thread *tdt;
8826201a50dSDmitry Chagin struct proc *p;
8836201a50dSDmitry Chagin int error;
8846201a50dSDmitry Chagin
8856201a50dSDmitry Chagin tdt = linux_tdfind(td, tid, tgid);
8866201a50dSDmitry Chagin if (tdt == NULL)
8876201a50dSDmitry Chagin return (ESRCH);
8886201a50dSDmitry Chagin
8896201a50dSDmitry Chagin p = tdt->td_proc;
8906201a50dSDmitry Chagin AUDIT_ARG_SIGNUM(sig);
8916201a50dSDmitry Chagin AUDIT_ARG_PID(p->p_pid);
8926201a50dSDmitry Chagin AUDIT_ARG_PROCESS(p);
8936201a50dSDmitry Chagin
8946201a50dSDmitry Chagin error = p_cansignal(td, p, sig);
8956201a50dSDmitry Chagin if (error != 0 || sig == 0)
8966201a50dSDmitry Chagin goto out;
8976201a50dSDmitry Chagin
8986201a50dSDmitry Chagin tdksignal(tdt, sig, ksi);
8996201a50dSDmitry Chagin
9006201a50dSDmitry Chagin out:
9016201a50dSDmitry Chagin PROC_UNLOCK(p);
9026201a50dSDmitry Chagin return (error);
9036201a50dSDmitry Chagin }
9046201a50dSDmitry Chagin
9056201a50dSDmitry Chagin static int
linux_tdsignal(struct thread * td,lwpid_t tid,int tgid,int sig)9066201a50dSDmitry Chagin linux_tdsignal(struct thread *td, lwpid_t tid, int tgid, int sig)
9076201a50dSDmitry Chagin {
9086201a50dSDmitry Chagin ksiginfo_t ksi;
9096201a50dSDmitry Chagin
9106201a50dSDmitry Chagin ksiginfo_init(&ksi);
9116201a50dSDmitry Chagin ksi.ksi_signo = sig;
9126201a50dSDmitry Chagin ksi.ksi_code = SI_LWP;
9136201a50dSDmitry Chagin ksi.ksi_pid = td->td_proc->p_pid;
9146201a50dSDmitry Chagin ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
9156201a50dSDmitry Chagin return (linux_tdksignal(td, tid, tgid, sig, &ksi));
9166201a50dSDmitry Chagin }
9176201a50dSDmitry Chagin
9186201a50dSDmitry Chagin static int
linux_pksignal(struct thread * td,int pid,int sig,ksiginfo_t * ksi)9196201a50dSDmitry Chagin linux_pksignal(struct thread *td, int pid, int sig, ksiginfo_t *ksi)
9206201a50dSDmitry Chagin {
9216201a50dSDmitry Chagin struct thread *tdt;
9226201a50dSDmitry Chagin struct proc *p;
9236201a50dSDmitry Chagin int error;
9246201a50dSDmitry Chagin
9256201a50dSDmitry Chagin tdt = linux_tdfind(td, pid, -1);
9266201a50dSDmitry Chagin if (tdt == NULL)
9276201a50dSDmitry Chagin return (ESRCH);
9286201a50dSDmitry Chagin
9296201a50dSDmitry Chagin p = tdt->td_proc;
9306201a50dSDmitry Chagin AUDIT_ARG_SIGNUM(sig);
9316201a50dSDmitry Chagin AUDIT_ARG_PID(p->p_pid);
9326201a50dSDmitry Chagin AUDIT_ARG_PROCESS(p);
9336201a50dSDmitry Chagin
9346201a50dSDmitry Chagin error = p_cansignal(td, p, sig);
9356201a50dSDmitry Chagin if (error != 0 || sig == 0)
9366201a50dSDmitry Chagin goto out;
9376201a50dSDmitry Chagin
9386201a50dSDmitry Chagin pksignal(p, sig, ksi);
9396201a50dSDmitry Chagin
9406201a50dSDmitry Chagin out:
9416201a50dSDmitry Chagin PROC_UNLOCK(p);
9426201a50dSDmitry Chagin return (error);
9436201a50dSDmitry Chagin }
9446201a50dSDmitry Chagin
9456201a50dSDmitry Chagin static int
linux_psignal(struct thread * td,int pid,int sig)9466201a50dSDmitry Chagin linux_psignal(struct thread *td, int pid, int sig)
9476201a50dSDmitry Chagin {
9486201a50dSDmitry Chagin ksiginfo_t ksi;
9496201a50dSDmitry Chagin
9506201a50dSDmitry Chagin ksiginfo_init(&ksi);
9516201a50dSDmitry Chagin ksi.ksi_signo = sig;
9526201a50dSDmitry Chagin ksi.ksi_code = SI_LWP;
9536201a50dSDmitry Chagin ksi.ksi_pid = td->td_proc->p_pid;
9546201a50dSDmitry Chagin ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
9556201a50dSDmitry Chagin return (linux_pksignal(td, pid, sig, &ksi));
9566201a50dSDmitry Chagin }
9573923e632SDmitry Chagin
9583923e632SDmitry Chagin int
linux_copyin_sigset(struct thread * td,l_sigset_t * lset,l_size_t sigsetsize,sigset_t * set,sigset_t ** pset)95993107373SDmitry Chagin linux_copyin_sigset(struct thread *td, l_sigset_t *lset,
96093107373SDmitry Chagin l_size_t sigsetsize, sigset_t *set, sigset_t **pset)
9613923e632SDmitry Chagin {
9623923e632SDmitry Chagin l_sigset_t lmask;
9633923e632SDmitry Chagin int error;
9643923e632SDmitry Chagin
9653923e632SDmitry Chagin if (sigsetsize != sizeof(l_sigset_t))
9663923e632SDmitry Chagin return (EINVAL);
9673923e632SDmitry Chagin if (lset != NULL) {
9682722e515SDmitry Chagin error = copyin(lset, &lmask, sizeof(lmask));
9693923e632SDmitry Chagin if (error != 0)
9703923e632SDmitry Chagin return (error);
9713923e632SDmitry Chagin linux_to_bsd_sigset(&lmask, set);
9723923e632SDmitry Chagin if (pset != NULL)
9733923e632SDmitry Chagin *pset = set;
97493107373SDmitry Chagin #ifdef KTRACE
97593107373SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
97693107373SDmitry Chagin linux_ktrsigset(&lmask, sizeof(lmask));
97793107373SDmitry Chagin #endif
9783923e632SDmitry Chagin } else if (pset != NULL)
9793923e632SDmitry Chagin *pset = NULL;
9803923e632SDmitry Chagin return (0);
9813923e632SDmitry Chagin }
982