1c21dee17SSøren Schmidt /*- 29a14aa01SUlrich Spörlein * Copyright (c) 1994-1995 Søren Schmidt 3c21dee17SSøren Schmidt * All rights reserved. 4c21dee17SSøren Schmidt * 5c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without 6c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions 7c21dee17SSøren Schmidt * are met: 8c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 9c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer 10c21dee17SSøren Schmidt * in this position and unchanged. 11c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 12c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 13c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution. 14c21dee17SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 1521dc7d4fSJens Schweikhardt * derived from this software without specific prior written permission 16c21dee17SSøren Schmidt * 17c21dee17SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18c21dee17SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19c21dee17SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20c21dee17SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21c21dee17SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22c21dee17SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23c21dee17SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24c21dee17SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25c21dee17SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26c21dee17SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27c21dee17SSøren Schmidt */ 28c21dee17SSøren Schmidt 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 301e8d246eSNate Lawson __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 32c21dee17SSøren Schmidt #include <sys/param.h> 33c21dee17SSøren Schmidt #include <sys/systm.h> 34fb919e4dSMark Murray #include <sys/lock.h> 35fb919e4dSMark Murray #include <sys/mutex.h> 3629ddc19bSAlexander Leidinger #include <sys/sx.h> 37c21dee17SSøren Schmidt #include <sys/proc.h> 38c21dee17SSøren Schmidt #include <sys/signalvar.h> 39206a5d3aSIan Dowse #include <sys/syscallsubr.h> 40fb919e4dSMark Murray #include <sys/sysproto.h> 41c21dee17SSøren Schmidt 42aa8b2011SKonstantin Belousov #include <security/audit/audit.h> 43aa8b2011SKonstantin Belousov 44aefce619SRuslan Ermilov #include "opt_compat.h" 45aefce619SRuslan Ermilov 461997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 474af27623STim J. Robbins #include <machine/../linux32/linux.h> 484af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h> 491997c537SDavid E. O'Brien #else 501997c537SDavid E. O'Brien #include <machine/../linux/linux.h> 511997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h> 524af27623STim J. Robbins #endif 53ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h> 54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h> 559b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h> 56*81338031SDmitry Chagin #include <compat/linux/linux_misc.h> 57*81338031SDmitry Chagin 58*81338031SDmitry Chagin static int linux_do_tkill(struct thread *td, struct thread *tdt, 59*81338031SDmitry Chagin ksiginfo_t *ksi); 609b44bfc5SAlexander Leidinger 61ba9ef45bSMarcel Moolenaar void 625002a60fSMarcel Moolenaar linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 63956d3333SMarcel Moolenaar { 64d66a5066SPeter Wemm int b, l; 65c21dee17SSøren Schmidt 66956d3333SMarcel Moolenaar SIGEMPTYSET(*bss); 67956d3333SMarcel Moolenaar bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 68956d3333SMarcel Moolenaar bss->__bits[1] = lss->__bits[1]; 69956d3333SMarcel Moolenaar for (l = 1; l <= LINUX_SIGTBLSZ; l++) { 70956d3333SMarcel Moolenaar if (LINUX_SIGISMEMBER(*lss, l)) { 71956d3333SMarcel Moolenaar b = linux_to_bsd_signal[_SIG_IDX(l)]; 72956d3333SMarcel Moolenaar if (b) 73956d3333SMarcel Moolenaar SIGADDSET(*bss, b); 74d66a5066SPeter Wemm } 75d66a5066SPeter Wemm } 76c21dee17SSøren Schmidt } 77c21dee17SSøren Schmidt 7879363394SAndrew Gallatin void 795002a60fSMarcel Moolenaar bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 80956d3333SMarcel Moolenaar { 81d66a5066SPeter Wemm int b, l; 82c21dee17SSøren Schmidt 83956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(*lss); 84956d3333SMarcel Moolenaar lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 85956d3333SMarcel Moolenaar lss->__bits[1] = bss->__bits[1]; 86956d3333SMarcel Moolenaar for (b = 1; b <= LINUX_SIGTBLSZ; b++) { 87956d3333SMarcel Moolenaar if (SIGISMEMBER(*bss, b)) { 88956d3333SMarcel Moolenaar l = bsd_to_linux_signal[_SIG_IDX(b)]; 89956d3333SMarcel Moolenaar if (l) 90956d3333SMarcel Moolenaar LINUX_SIGADDSET(*lss, l); 91d66a5066SPeter Wemm } 92d66a5066SPeter Wemm } 93c21dee17SSøren Schmidt } 94c21dee17SSøren Schmidt 95a1ebcbfbSPeter Wemm static void 965002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa) 97d66a5066SPeter Wemm { 98956d3333SMarcel Moolenaar 99956d3333SMarcel Moolenaar linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); 1004af27623STim J. Robbins bsa->sa_handler = PTRIN(lsa->lsa_handler); 101d66a5066SPeter Wemm bsa->sa_flags = 0; 1028f437f44SMartin Cracauer if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) 103d66a5066SPeter Wemm bsa->sa_flags |= SA_NOCLDSTOP; 10406ebbe77SMarcel Moolenaar if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) 10506ebbe77SMarcel Moolenaar bsa->sa_flags |= SA_NOCLDWAIT; 10606ebbe77SMarcel Moolenaar if (lsa->lsa_flags & LINUX_SA_SIGINFO) 10706ebbe77SMarcel Moolenaar bsa->sa_flags |= SA_SIGINFO; 1088f437f44SMartin Cracauer if (lsa->lsa_flags & LINUX_SA_ONSTACK) 109d66a5066SPeter Wemm bsa->sa_flags |= SA_ONSTACK; 1108f437f44SMartin Cracauer if (lsa->lsa_flags & LINUX_SA_RESTART) 111d66a5066SPeter Wemm bsa->sa_flags |= SA_RESTART; 1128f437f44SMartin Cracauer if (lsa->lsa_flags & LINUX_SA_ONESHOT) 113d66a5066SPeter Wemm bsa->sa_flags |= SA_RESETHAND; 1148f437f44SMartin Cracauer if (lsa->lsa_flags & LINUX_SA_NOMASK) 115d66a5066SPeter Wemm bsa->sa_flags |= SA_NODEFER; 116d66a5066SPeter Wemm } 117d66a5066SPeter Wemm 118a1ebcbfbSPeter Wemm static void 1195002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa) 120d66a5066SPeter Wemm { 121956d3333SMarcel Moolenaar 122956d3333SMarcel Moolenaar bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); 1231997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 1244af27623STim J. Robbins lsa->lsa_handler = (uintptr_t)bsa->sa_handler; 1254af27623STim J. Robbins #else 1268f437f44SMartin Cracauer lsa->lsa_handler = bsa->sa_handler; 1274af27623STim J. Robbins #endif 1284af27623STim J. Robbins lsa->lsa_restorer = 0; /* unsupported */ 1298f437f44SMartin Cracauer lsa->lsa_flags = 0; 130d66a5066SPeter Wemm if (bsa->sa_flags & SA_NOCLDSTOP) 1318f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; 13206ebbe77SMarcel Moolenaar if (bsa->sa_flags & SA_NOCLDWAIT) 13306ebbe77SMarcel Moolenaar lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; 13406ebbe77SMarcel Moolenaar if (bsa->sa_flags & SA_SIGINFO) 13506ebbe77SMarcel Moolenaar lsa->lsa_flags |= LINUX_SA_SIGINFO; 136d66a5066SPeter Wemm if (bsa->sa_flags & SA_ONSTACK) 1378f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_ONSTACK; 138d66a5066SPeter Wemm if (bsa->sa_flags & SA_RESTART) 1398f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_RESTART; 140d66a5066SPeter Wemm if (bsa->sa_flags & SA_RESETHAND) 1418f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_ONESHOT; 142d66a5066SPeter Wemm if (bsa->sa_flags & SA_NODEFER) 1438f437f44SMartin Cracauer lsa->lsa_flags |= LINUX_SA_NOMASK; 144d66a5066SPeter Wemm } 145c21dee17SSøren Schmidt 146ba9ef45bSMarcel Moolenaar int 147b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa, 1485002a60fSMarcel Moolenaar l_sigaction_t *linux_osa) 14906ebbe77SMarcel Moolenaar { 150206a5d3aSIan Dowse struct sigaction act, oact, *nsa, *osa; 151206a5d3aSIan Dowse int error, sig; 15206ebbe77SMarcel Moolenaar 153687c23beSAlexander Leidinger if (!LINUX_SIG_VALID(linux_sig)) 154956d3333SMarcel Moolenaar return (EINVAL); 15506ebbe77SMarcel Moolenaar 156206a5d3aSIan Dowse osa = (linux_osa != NULL) ? &oact : NULL; 157956d3333SMarcel Moolenaar if (linux_nsa != NULL) { 158206a5d3aSIan Dowse nsa = &act; 159ec99e322SMarcel Moolenaar linux_to_bsd_sigaction(linux_nsa, nsa); 160206a5d3aSIan Dowse } else 16106ebbe77SMarcel Moolenaar nsa = NULL; 16206ebbe77SMarcel Moolenaar 163956d3333SMarcel Moolenaar if (linux_sig <= LINUX_SIGTBLSZ) 164206a5d3aSIan Dowse sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; 165956d3333SMarcel Moolenaar else 166206a5d3aSIan Dowse sig = linux_sig; 167956d3333SMarcel Moolenaar 168206a5d3aSIan Dowse error = kern_sigaction(td, sig, nsa, osa, 0); 16906ebbe77SMarcel Moolenaar if (error) 170956d3333SMarcel Moolenaar return (error); 17106ebbe77SMarcel Moolenaar 172ec99e322SMarcel Moolenaar if (linux_osa != NULL) 173ec99e322SMarcel Moolenaar bsd_to_linux_sigaction(osa, linux_osa); 17406ebbe77SMarcel Moolenaar 175956d3333SMarcel Moolenaar return (0); 17606ebbe77SMarcel Moolenaar } 17706ebbe77SMarcel Moolenaar 1785231fb20SDavid E. O'Brien 179c21dee17SSøren Schmidt int 180b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args) 181d66a5066SPeter Wemm { 1825002a60fSMarcel Moolenaar l_sigaction_t nsa, osa; 183d66a5066SPeter Wemm int error; 184d66a5066SPeter Wemm 185d66a5066SPeter Wemm #ifdef DEBUG 18624593369SJonathan Lemon if (ldebug(signal)) 18724593369SJonathan Lemon printf(ARGS(signal, "%d, %p"), 188b61c60d4SDavid E. O'Brien args->sig, (void *)(uintptr_t)args->handler); 189d66a5066SPeter Wemm #endif 190d66a5066SPeter Wemm 19106ebbe77SMarcel Moolenaar nsa.lsa_handler = args->handler; 19206ebbe77SMarcel Moolenaar nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 193956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(nsa.lsa_mask); 194d66a5066SPeter Wemm 195b40ce416SJulian Elischer error = linux_do_sigaction(td, args->sig, &nsa, &osa); 1964af27623STim J. Robbins td->td_retval[0] = (int)(intptr_t)osa.lsa_handler; 197d66a5066SPeter Wemm 198956d3333SMarcel Moolenaar return (error); 199d66a5066SPeter Wemm } 200d66a5066SPeter Wemm 201c21dee17SSøren Schmidt int 202b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args) 203c21dee17SSøren Schmidt { 2045002a60fSMarcel Moolenaar l_sigaction_t nsa, osa; 20506ebbe77SMarcel Moolenaar int error; 206c21dee17SSøren Schmidt 207c21dee17SSøren Schmidt #ifdef DEBUG 20824593369SJonathan Lemon if (ldebug(rt_sigaction)) 20924593369SJonathan Lemon printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), 21024593369SJonathan Lemon (long)args->sig, (void *)args->act, 2115231fb20SDavid E. O'Brien (void *)args->oact, (long)args->sigsetsize); 212c21dee17SSøren Schmidt #endif 213d66a5066SPeter Wemm 2145002a60fSMarcel Moolenaar if (args->sigsetsize != sizeof(l_sigset_t)) 215956d3333SMarcel Moolenaar return (EINVAL); 21606ebbe77SMarcel Moolenaar 217956d3333SMarcel Moolenaar if (args->act != NULL) { 2185002a60fSMarcel Moolenaar error = copyin(args->act, &nsa, sizeof(l_sigaction_t)); 21906ebbe77SMarcel Moolenaar if (error) 220956d3333SMarcel Moolenaar return (error); 22106ebbe77SMarcel Moolenaar } 22206ebbe77SMarcel Moolenaar 223b40ce416SJulian Elischer error = linux_do_sigaction(td, args->sig, 22406ebbe77SMarcel Moolenaar args->act ? &nsa : NULL, 22506ebbe77SMarcel Moolenaar args->oact ? &osa : NULL); 22606ebbe77SMarcel Moolenaar 227956d3333SMarcel Moolenaar if (args->oact != NULL && !error) { 2285002a60fSMarcel Moolenaar error = copyout(&osa, args->oact, sizeof(l_sigaction_t)); 22906ebbe77SMarcel Moolenaar } 23006ebbe77SMarcel Moolenaar 231956d3333SMarcel Moolenaar return (error); 23206ebbe77SMarcel Moolenaar } 23306ebbe77SMarcel Moolenaar 23406ebbe77SMarcel Moolenaar static int 235b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new, 2365002a60fSMarcel Moolenaar l_sigset_t *old) 23706ebbe77SMarcel Moolenaar { 238fe8cdcaeSJohn Baldwin sigset_t omask, nmask; 239fe8cdcaeSJohn Baldwin sigset_t *nmaskp; 240216af822SJohn Baldwin int error; 24106ebbe77SMarcel Moolenaar 242b40ce416SJulian Elischer td->td_retval[0] = 0; 243d66a5066SPeter Wemm 24419dde5cdSJohn Baldwin switch (how) { 24519dde5cdSJohn Baldwin case LINUX_SIG_BLOCK: 24619dde5cdSJohn Baldwin how = SIG_BLOCK; 24719dde5cdSJohn Baldwin break; 24819dde5cdSJohn Baldwin case LINUX_SIG_UNBLOCK: 24919dde5cdSJohn Baldwin how = SIG_UNBLOCK; 25019dde5cdSJohn Baldwin break; 25119dde5cdSJohn Baldwin case LINUX_SIG_SETMASK: 25219dde5cdSJohn Baldwin how = SIG_SETMASK; 25319dde5cdSJohn Baldwin break; 25419dde5cdSJohn Baldwin default: 25519dde5cdSJohn Baldwin return (EINVAL); 25619dde5cdSJohn Baldwin } 25706ebbe77SMarcel Moolenaar if (new != NULL) { 258fe8cdcaeSJohn Baldwin linux_to_bsd_sigset(new, &nmask); 259fe8cdcaeSJohn Baldwin nmaskp = &nmask; 260fe8cdcaeSJohn Baldwin } else 261fe8cdcaeSJohn Baldwin nmaskp = NULL; 26219dde5cdSJohn Baldwin error = kern_sigprocmask(td, how, nmaskp, &omask, 0); 2632f7ed219SJohn Baldwin if (error == 0 && old != NULL) 264fe8cdcaeSJohn Baldwin bsd_to_linux_sigset(&omask, old); 26506ebbe77SMarcel Moolenaar 266956d3333SMarcel Moolenaar return (error); 26706ebbe77SMarcel Moolenaar } 26806ebbe77SMarcel Moolenaar 26906ebbe77SMarcel Moolenaar int 270b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args) 27106ebbe77SMarcel Moolenaar { 2725002a60fSMarcel Moolenaar l_osigset_t mask; 2735002a60fSMarcel Moolenaar l_sigset_t set, oset; 27406ebbe77SMarcel Moolenaar int error; 27506ebbe77SMarcel Moolenaar 27606ebbe77SMarcel Moolenaar #ifdef DEBUG 27724593369SJonathan Lemon if (ldebug(sigprocmask)) 27824593369SJonathan Lemon printf(ARGS(sigprocmask, "%d, *, *"), args->how); 27906ebbe77SMarcel Moolenaar #endif 28006ebbe77SMarcel Moolenaar 28106ebbe77SMarcel Moolenaar if (args->mask != NULL) { 2825002a60fSMarcel Moolenaar error = copyin(args->mask, &mask, sizeof(l_osigset_t)); 28306ebbe77SMarcel Moolenaar if (error) 284956d3333SMarcel Moolenaar return (error); 285956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(set); 286956d3333SMarcel Moolenaar set.__bits[0] = mask; 28706ebbe77SMarcel Moolenaar } 28806ebbe77SMarcel Moolenaar 289b40ce416SJulian Elischer error = linux_do_sigprocmask(td, args->how, 290956d3333SMarcel Moolenaar args->mask ? &set : NULL, 291956d3333SMarcel Moolenaar args->omask ? &oset : NULL); 29206ebbe77SMarcel Moolenaar 293956d3333SMarcel Moolenaar if (args->omask != NULL && !error) { 294956d3333SMarcel Moolenaar mask = oset.__bits[0]; 2955002a60fSMarcel Moolenaar error = copyout(&mask, args->omask, sizeof(l_osigset_t)); 29606ebbe77SMarcel Moolenaar } 29706ebbe77SMarcel Moolenaar 298956d3333SMarcel Moolenaar return (error); 29906ebbe77SMarcel Moolenaar } 30006ebbe77SMarcel Moolenaar 30106ebbe77SMarcel Moolenaar int 302b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args) 30306ebbe77SMarcel Moolenaar { 3045002a60fSMarcel Moolenaar l_sigset_t set, oset; 30506ebbe77SMarcel Moolenaar int error; 30606ebbe77SMarcel Moolenaar 30706ebbe77SMarcel Moolenaar #ifdef DEBUG 30824593369SJonathan Lemon if (ldebug(rt_sigprocmask)) 30924593369SJonathan Lemon printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 31024593369SJonathan Lemon args->how, (void *)args->mask, 3115231fb20SDavid E. O'Brien (void *)args->omask, (long)args->sigsetsize); 31206ebbe77SMarcel Moolenaar #endif 31306ebbe77SMarcel Moolenaar 3145002a60fSMarcel Moolenaar if (args->sigsetsize != sizeof(l_sigset_t)) 31506ebbe77SMarcel Moolenaar return EINVAL; 31606ebbe77SMarcel Moolenaar 31706ebbe77SMarcel Moolenaar if (args->mask != NULL) { 3185002a60fSMarcel Moolenaar error = copyin(args->mask, &set, sizeof(l_sigset_t)); 31906ebbe77SMarcel Moolenaar if (error) 320956d3333SMarcel Moolenaar return (error); 32106ebbe77SMarcel Moolenaar } 32206ebbe77SMarcel Moolenaar 323b40ce416SJulian Elischer error = linux_do_sigprocmask(td, args->how, 324956d3333SMarcel Moolenaar args->mask ? &set : NULL, 325956d3333SMarcel Moolenaar args->omask ? &oset : NULL); 32606ebbe77SMarcel Moolenaar 327956d3333SMarcel Moolenaar if (args->omask != NULL && !error) { 3285002a60fSMarcel Moolenaar error = copyout(&oset, args->omask, sizeof(l_sigset_t)); 32906ebbe77SMarcel Moolenaar } 33006ebbe77SMarcel Moolenaar 331956d3333SMarcel Moolenaar return (error); 332c21dee17SSøren Schmidt } 333c21dee17SSøren Schmidt 334c21dee17SSøren Schmidt int 335b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args) 336c21dee17SSøren Schmidt { 337b40ce416SJulian Elischer struct proc *p = td->td_proc; 3385002a60fSMarcel Moolenaar l_sigset_t mask; 339956d3333SMarcel Moolenaar 340c21dee17SSøren Schmidt #ifdef DEBUG 3415002a60fSMarcel Moolenaar if (ldebug(sgetmask)) 3425002a60fSMarcel Moolenaar printf(ARGS(sgetmask, "")); 343c21dee17SSøren Schmidt #endif 344956d3333SMarcel Moolenaar 345216af822SJohn Baldwin PROC_LOCK(p); 3464093529dSJeff Roberson bsd_to_linux_sigset(&td->td_sigmask, &mask); 347216af822SJohn Baldwin PROC_UNLOCK(p); 348b40ce416SJulian Elischer td->td_retval[0] = mask.__bits[0]; 349956d3333SMarcel Moolenaar return (0); 350c21dee17SSøren Schmidt } 351c21dee17SSøren Schmidt 352c21dee17SSøren Schmidt int 353b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) 354c21dee17SSøren Schmidt { 355b40ce416SJulian Elischer struct proc *p = td->td_proc; 3565002a60fSMarcel Moolenaar l_sigset_t lset; 357956d3333SMarcel Moolenaar sigset_t bset; 358c21dee17SSøren Schmidt 359c21dee17SSøren Schmidt #ifdef DEBUG 3605002a60fSMarcel Moolenaar if (ldebug(ssetmask)) 3615002a60fSMarcel Moolenaar printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); 362c21dee17SSøren Schmidt #endif 363d66a5066SPeter Wemm 364216af822SJohn Baldwin PROC_LOCK(p); 3654093529dSJeff Roberson bsd_to_linux_sigset(&td->td_sigmask, &lset); 366b40ce416SJulian Elischer td->td_retval[0] = lset.__bits[0]; 367956d3333SMarcel Moolenaar LINUX_SIGEMPTYSET(lset); 368956d3333SMarcel Moolenaar lset.__bits[0] = args->mask; 369956d3333SMarcel Moolenaar linux_to_bsd_sigset(&lset, &bset); 3704093529dSJeff Roberson td->td_sigmask = bset; 3714093529dSJeff Roberson SIG_CANTMASK(td->td_sigmask); 3724093529dSJeff Roberson signotify(td); 373216af822SJohn Baldwin PROC_UNLOCK(p); 374956d3333SMarcel Moolenaar return (0); 375c21dee17SSøren Schmidt } 376c21dee17SSøren Schmidt 3775d58e285STim J. Robbins /* 3785d58e285STim J. Robbins * MPSAFE 3795d58e285STim J. Robbins */ 380c21dee17SSøren Schmidt int 381b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args) 382c21dee17SSøren Schmidt { 383b40ce416SJulian Elischer struct proc *p = td->td_proc; 384956d3333SMarcel Moolenaar sigset_t bset; 3855002a60fSMarcel Moolenaar l_sigset_t lset; 3865002a60fSMarcel Moolenaar l_osigset_t mask; 387c21dee17SSøren Schmidt 388c21dee17SSøren Schmidt #ifdef DEBUG 38924593369SJonathan Lemon if (ldebug(sigpending)) 39024593369SJonathan Lemon printf(ARGS(sigpending, "*")); 391c21dee17SSøren Schmidt #endif 392956d3333SMarcel Moolenaar 393216af822SJohn Baldwin PROC_LOCK(p); 3941d9c5696SJuli Mallett bset = p->p_siglist; 3954093529dSJeff Roberson SIGSETOR(bset, td->td_siglist); 3964093529dSJeff Roberson SIGSETAND(bset, td->td_sigmask); 397216af822SJohn Baldwin PROC_UNLOCK(p); 3989d8643ecSJohn Baldwin bsd_to_linux_sigset(&bset, &lset); 399956d3333SMarcel Moolenaar mask = lset.__bits[0]; 400956d3333SMarcel Moolenaar return (copyout(&mask, args->mask, sizeof(mask))); 401c21dee17SSøren Schmidt } 40217138b61SAlexander Leidinger 40317138b61SAlexander Leidinger /* 40417138b61SAlexander Leidinger * MPSAFE 40517138b61SAlexander Leidinger */ 40617138b61SAlexander Leidinger int 40717138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args) 40817138b61SAlexander Leidinger { 40917138b61SAlexander Leidinger struct proc *p = td->td_proc; 41017138b61SAlexander Leidinger sigset_t bset; 41117138b61SAlexander Leidinger l_sigset_t lset; 41217138b61SAlexander Leidinger 41317138b61SAlexander Leidinger if (args->sigsetsize > sizeof(lset)) 41417138b61SAlexander Leidinger return EINVAL; 41517138b61SAlexander Leidinger /* NOT REACHED */ 41617138b61SAlexander Leidinger 41717138b61SAlexander Leidinger #ifdef DEBUG 41817138b61SAlexander Leidinger if (ldebug(rt_sigpending)) 41917138b61SAlexander Leidinger printf(ARGS(rt_sigpending, "*")); 42017138b61SAlexander Leidinger #endif 42117138b61SAlexander Leidinger 42217138b61SAlexander Leidinger PROC_LOCK(p); 42317138b61SAlexander Leidinger bset = p->p_siglist; 42417138b61SAlexander Leidinger SIGSETOR(bset, td->td_siglist); 42517138b61SAlexander Leidinger SIGSETAND(bset, td->td_sigmask); 42617138b61SAlexander Leidinger PROC_UNLOCK(p); 42717138b61SAlexander Leidinger bsd_to_linux_sigset(&bset, &lset); 42817138b61SAlexander Leidinger return (copyout(&lset, args->set, args->sigsetsize)); 42917138b61SAlexander Leidinger } 430c21dee17SSøren Schmidt 431c9447c75SAlexander Leidinger /* 432c9447c75SAlexander Leidinger * MPSAFE 433c9447c75SAlexander Leidinger */ 434c9447c75SAlexander Leidinger int 435c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td, 436c9447c75SAlexander Leidinger struct linux_rt_sigtimedwait_args *args) 437c9447c75SAlexander Leidinger { 438f3481dd9SDmitry Chagin int error, sig; 439c9447c75SAlexander Leidinger l_timeval ltv; 440c9447c75SAlexander Leidinger struct timeval tv; 441c9447c75SAlexander Leidinger struct timespec ts, *tsa; 442c9447c75SAlexander Leidinger l_sigset_t lset; 443c9447c75SAlexander Leidinger sigset_t bset; 444c9447c75SAlexander Leidinger l_siginfo_t linfo; 445c9447c75SAlexander Leidinger ksiginfo_t info; 446c9447c75SAlexander Leidinger 447c9447c75SAlexander Leidinger #ifdef DEBUG 448c9447c75SAlexander Leidinger if (ldebug(rt_sigtimedwait)) 449c9447c75SAlexander Leidinger printf(ARGS(rt_sigtimedwait, "*")); 450c9447c75SAlexander Leidinger #endif 451c9447c75SAlexander Leidinger if (args->sigsetsize != sizeof(l_sigset_t)) 452c9447c75SAlexander Leidinger return (EINVAL); 453c9447c75SAlexander Leidinger 454c9447c75SAlexander Leidinger if ((error = copyin(args->mask, &lset, sizeof(lset)))) 455c9447c75SAlexander Leidinger return (error); 456c9447c75SAlexander Leidinger linux_to_bsd_sigset(&lset, &bset); 457c9447c75SAlexander Leidinger 458c9447c75SAlexander Leidinger tsa = NULL; 459c9447c75SAlexander Leidinger if (args->timeout) { 460c9447c75SAlexander Leidinger if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 461c9447c75SAlexander Leidinger return (error); 462c9447c75SAlexander Leidinger #ifdef DEBUG 463c9447c75SAlexander Leidinger if (ldebug(rt_sigtimedwait)) 4648c50c562SDmitry Chagin printf(LMSG("linux_rt_sigtimedwait: " 4658c50c562SDmitry Chagin "incoming timeout (%d/%d)\n"), 466c9447c75SAlexander Leidinger ltv.tv_sec, ltv.tv_usec); 467c9447c75SAlexander Leidinger #endif 468c9447c75SAlexander Leidinger tv.tv_sec = (long)ltv.tv_sec; 469c9447c75SAlexander Leidinger tv.tv_usec = (suseconds_t)ltv.tv_usec; 470c9447c75SAlexander Leidinger if (itimerfix(&tv)) { 471c9447c75SAlexander Leidinger /* 472c9447c75SAlexander Leidinger * The timeout was invalid. Convert it to something 473c9447c75SAlexander Leidinger * valid that will act as it does under Linux. 474c9447c75SAlexander Leidinger */ 475c9447c75SAlexander Leidinger tv.tv_sec += tv.tv_usec / 1000000; 476c9447c75SAlexander Leidinger tv.tv_usec %= 1000000; 477c9447c75SAlexander Leidinger if (tv.tv_usec < 0) { 478c9447c75SAlexander Leidinger tv.tv_sec -= 1; 479c9447c75SAlexander Leidinger tv.tv_usec += 1000000; 480c9447c75SAlexander Leidinger } 481c9447c75SAlexander Leidinger if (tv.tv_sec < 0) 482c9447c75SAlexander Leidinger timevalclear(&tv); 483c9447c75SAlexander Leidinger #ifdef DEBUG 484c9447c75SAlexander Leidinger if (ldebug(rt_sigtimedwait)) 4858c50c562SDmitry Chagin printf(LMSG("linux_rt_sigtimedwait: " 4868c50c562SDmitry Chagin "converted timeout (%jd/%ld)\n"), 48759038483SXin LI (intmax_t)tv.tv_sec, tv.tv_usec); 488c9447c75SAlexander Leidinger #endif 489c9447c75SAlexander Leidinger } 490c9447c75SAlexander Leidinger TIMEVAL_TO_TIMESPEC(&tv, &ts); 491c9447c75SAlexander Leidinger tsa = &ts; 492c9447c75SAlexander Leidinger } 493c9447c75SAlexander Leidinger error = kern_sigtimedwait(td, bset, &info, tsa); 494c9447c75SAlexander Leidinger #ifdef DEBUG 495c9447c75SAlexander Leidinger if (ldebug(rt_sigtimedwait)) 4968c50c562SDmitry Chagin printf(LMSG("linux_rt_sigtimedwait: " 4978c50c562SDmitry Chagin "sigtimedwait returning (%d)\n"), error); 498c9447c75SAlexander Leidinger #endif 499c9447c75SAlexander Leidinger if (error) 500c9447c75SAlexander Leidinger return (error); 501c9447c75SAlexander Leidinger 502f3481dd9SDmitry Chagin sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo); 503f3481dd9SDmitry Chagin 504c9447c75SAlexander Leidinger if (args->ptr) { 505c9447c75SAlexander Leidinger memset(&linfo, 0, sizeof(linfo)); 506f3481dd9SDmitry Chagin ksiginfo_to_lsiginfo(&info, &linfo, sig); 507c9447c75SAlexander Leidinger error = copyout(&linfo, args->ptr, sizeof(linfo)); 508c9447c75SAlexander Leidinger } 509f3481dd9SDmitry Chagin if (error == 0) 510f3481dd9SDmitry Chagin td->td_retval[0] = sig; 511c9447c75SAlexander Leidinger 512c9447c75SAlexander Leidinger return (error); 513c9447c75SAlexander Leidinger } 514c9447c75SAlexander Leidinger 515c21dee17SSøren Schmidt int 516b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args) 517c21dee17SSøren Schmidt { 518ef04503dSPeter Wemm struct kill_args /* { 519c21dee17SSøren Schmidt int pid; 520c21dee17SSøren Schmidt int signum; 521ef04503dSPeter Wemm } */ tmp; 522c21dee17SSøren Schmidt 523c21dee17SSøren Schmidt #ifdef DEBUG 52424593369SJonathan Lemon if (ldebug(kill)) 52524593369SJonathan Lemon printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 526c21dee17SSøren Schmidt #endif 527956d3333SMarcel Moolenaar 528956d3333SMarcel Moolenaar /* 529956d3333SMarcel Moolenaar * Allow signal 0 as a means to check for privileges 530956d3333SMarcel Moolenaar */ 53164742216SAlexander Leidinger if (!LINUX_SIG_VALID(args->signum) && args->signum != 0) 5329a6a64d3SDmitry Chagin return (EINVAL); 533956d3333SMarcel Moolenaar 534956d3333SMarcel Moolenaar if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 535956d3333SMarcel Moolenaar tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 536956d3333SMarcel Moolenaar else 537956d3333SMarcel Moolenaar tmp.signum = args->signum; 538956d3333SMarcel Moolenaar 539c21dee17SSøren Schmidt tmp.pid = args->pid; 5408451d0ddSKip Macy return (sys_kill(td, &tmp)); 541c21dee17SSøren Schmidt } 5429b44bfc5SAlexander Leidinger 543aa8b2011SKonstantin Belousov static int 544*81338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi) 545aa8b2011SKonstantin Belousov { 546aa8b2011SKonstantin Belousov struct proc *p; 547aa8b2011SKonstantin Belousov int error; 548aa8b2011SKonstantin Belousov 549*81338031SDmitry Chagin p = tdt->td_proc; 550*81338031SDmitry Chagin AUDIT_ARG_SIGNUM(ksi->ksi_signo); 551*81338031SDmitry Chagin AUDIT_ARG_PID(p->p_pid); 55214961ba7SRobert Watson AUDIT_ARG_PROCESS(p); 553*81338031SDmitry Chagin 554*81338031SDmitry Chagin error = p_cansignal(td, p, ksi->ksi_signo); 555*81338031SDmitry Chagin if (error != 0 || ksi->ksi_signo == 0) 556aa8b2011SKonstantin Belousov goto out; 557aa8b2011SKonstantin Belousov 558*81338031SDmitry Chagin tdksignal(tdt, ksi->ksi_signo, ksi); 559aa8b2011SKonstantin Belousov 560aa8b2011SKonstantin Belousov out: 561aa8b2011SKonstantin Belousov PROC_UNLOCK(p); 562aa8b2011SKonstantin Belousov return (error); 563aa8b2011SKonstantin Belousov } 564aa8b2011SKonstantin Belousov 5659b44bfc5SAlexander Leidinger int 5669b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args) 5679b44bfc5SAlexander Leidinger { 568*81338031SDmitry Chagin struct thread *tdt; 569*81338031SDmitry Chagin ksiginfo_t ksi; 570*81338031SDmitry Chagin int sig; 5719b44bfc5SAlexander Leidinger 5729b44bfc5SAlexander Leidinger #ifdef DEBUG 5739b44bfc5SAlexander Leidinger if (ldebug(tgkill)) 574*81338031SDmitry Chagin printf(ARGS(tgkill, "%d, %d, %d"), 575*81338031SDmitry Chagin args->tgid, args->pid, args->sig); 5769b44bfc5SAlexander Leidinger #endif 577*81338031SDmitry Chagin 578aa8b2011SKonstantin Belousov if (args->pid <= 0 || args->tgid <=0) 579aa8b2011SKonstantin Belousov return (EINVAL); 5809b44bfc5SAlexander Leidinger 581*81338031SDmitry Chagin /* 582*81338031SDmitry Chagin * Allow signal 0 as a means to check for privileges 583*81338031SDmitry Chagin */ 584*81338031SDmitry Chagin if (!LINUX_SIG_VALID(args->sig) && args->sig != 0) 585*81338031SDmitry Chagin return (EINVAL); 586*81338031SDmitry Chagin 587*81338031SDmitry Chagin if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ) 588*81338031SDmitry Chagin sig = linux_to_bsd_signal[_SIG_IDX(args->sig)]; 589*81338031SDmitry Chagin else 590*81338031SDmitry Chagin sig = args->sig; 591*81338031SDmitry Chagin 592*81338031SDmitry Chagin tdt = linux_tdfind(td, args->pid, args->tgid); 593*81338031SDmitry Chagin if (tdt == NULL) 594*81338031SDmitry Chagin return (ESRCH); 595*81338031SDmitry Chagin 596*81338031SDmitry Chagin ksiginfo_init(&ksi); 597*81338031SDmitry Chagin ksi.ksi_signo = sig; 598*81338031SDmitry Chagin ksi.ksi_code = LINUX_SI_TKILL; 599*81338031SDmitry Chagin ksi.ksi_errno = 0; 600*81338031SDmitry Chagin ksi.ksi_pid = td->td_proc->p_pid; 601*81338031SDmitry Chagin ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid; 602*81338031SDmitry Chagin return (linux_do_tkill(td, tdt, &ksi)); 6039b44bfc5SAlexander Leidinger } 6049b44bfc5SAlexander Leidinger 605*81338031SDmitry Chagin /* 606*81338031SDmitry Chagin * Deprecated since 2.5.75. Replaced by tgkill(). 607*81338031SDmitry Chagin */ 6089b44bfc5SAlexander Leidinger int 6099b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args) 6109b44bfc5SAlexander Leidinger { 611*81338031SDmitry Chagin struct thread *tdt; 612*81338031SDmitry Chagin ksiginfo_t ksi; 613*81338031SDmitry Chagin int sig; 614*81338031SDmitry Chagin 6159b44bfc5SAlexander Leidinger #ifdef DEBUG 6169b44bfc5SAlexander Leidinger if (ldebug(tkill)) 6179b44bfc5SAlexander Leidinger printf(ARGS(tkill, "%i, %i"), args->tid, args->sig); 6189b44bfc5SAlexander Leidinger #endif 619aa8b2011SKonstantin Belousov if (args->tid <= 0) 620aa8b2011SKonstantin Belousov return (EINVAL); 6219b44bfc5SAlexander Leidinger 622*81338031SDmitry Chagin if (!LINUX_SIG_VALID(args->sig)) 623*81338031SDmitry Chagin return (EINVAL); 624*81338031SDmitry Chagin 625*81338031SDmitry Chagin if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ) 626*81338031SDmitry Chagin sig = linux_to_bsd_signal[_SIG_IDX(args->sig)]; 627*81338031SDmitry Chagin else 628*81338031SDmitry Chagin sig = args->sig; 629*81338031SDmitry Chagin 630*81338031SDmitry Chagin tdt = linux_tdfind(td, args->tid, -1); 631*81338031SDmitry Chagin if (tdt == NULL) 632*81338031SDmitry Chagin return (ESRCH); 633*81338031SDmitry Chagin 634*81338031SDmitry Chagin ksiginfo_init(&ksi); 635*81338031SDmitry Chagin ksi.ksi_signo = sig; 636*81338031SDmitry Chagin ksi.ksi_code = LINUX_SI_TKILL; 637*81338031SDmitry Chagin ksi.ksi_errno = 0; 638*81338031SDmitry Chagin ksi.ksi_pid = td->td_proc->p_pid; 639*81338031SDmitry Chagin ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid; 640*81338031SDmitry Chagin return (linux_do_tkill(td, tdt, &ksi)); 641aa8b2011SKonstantin Belousov } 642aa8b2011SKonstantin Belousov 643aa8b2011SKonstantin Belousov void 644aa8b2011SKonstantin Belousov ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig) 645aa8b2011SKonstantin Belousov { 646aa8b2011SKonstantin Belousov 647aa8b2011SKonstantin Belousov lsi->lsi_signo = sig; 648aa8b2011SKonstantin Belousov lsi->lsi_code = ksi->ksi_code; 649aa8b2011SKonstantin Belousov 650aa8b2011SKonstantin Belousov switch (sig) { 651aa8b2011SKonstantin Belousov case LINUX_SIGPOLL: 652aa8b2011SKonstantin Belousov /* XXX si_fd? */ 653aa8b2011SKonstantin Belousov lsi->lsi_band = ksi->ksi_band; 654aa8b2011SKonstantin Belousov break; 655aa8b2011SKonstantin Belousov case LINUX_SIGCHLD: 656aa8b2011SKonstantin Belousov lsi->lsi_pid = ksi->ksi_pid; 657aa8b2011SKonstantin Belousov lsi->lsi_uid = ksi->ksi_uid; 658aa8b2011SKonstantin Belousov lsi->lsi_status = ksi->ksi_status; 659aa8b2011SKonstantin Belousov break; 660aa8b2011SKonstantin Belousov case LINUX_SIGBUS: 661aa8b2011SKonstantin Belousov case LINUX_SIGILL: 662aa8b2011SKonstantin Belousov case LINUX_SIGFPE: 663aa8b2011SKonstantin Belousov case LINUX_SIGSEGV: 664aa8b2011SKonstantin Belousov lsi->lsi_addr = PTROUT(ksi->ksi_addr); 665aa8b2011SKonstantin Belousov break; 666aa8b2011SKonstantin Belousov default: 667aa8b2011SKonstantin Belousov /* XXX SI_TIMER etc... */ 668aa8b2011SKonstantin Belousov lsi->lsi_pid = ksi->ksi_pid; 669aa8b2011SKonstantin Belousov lsi->lsi_uid = ksi->ksi_uid; 670aa8b2011SKonstantin Belousov break; 671aa8b2011SKonstantin Belousov } 67209d6cb0aSDmitry Chagin if (sig >= LINUX_SIGRTMIN) { 67309d6cb0aSDmitry Chagin lsi->lsi_int = ksi->ksi_info.si_value.sival_int; 67409d6cb0aSDmitry Chagin lsi->lsi_ptr = PTROUT(ksi->ksi_info.si_value.sival_ptr); 67509d6cb0aSDmitry Chagin } 6769b44bfc5SAlexander Leidinger } 677