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