linux_signal.c revision 104306
19313Ssos/*- 29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt 39313Ssos * All rights reserved. 49313Ssos * 59313Ssos * Redistribution and use in source and binary forms, with or without 69313Ssos * modification, are permitted provided that the following conditions 79313Ssos * are met: 89313Ssos * 1. Redistributions of source code must retain the above copyright 99313Ssos * notice, this list of conditions and the following disclaimer 109313Ssos * in this position and unchanged. 119313Ssos * 2. Redistributions in binary form must reproduce the above copyright 129313Ssos * notice, this list of conditions and the following disclaimer in the 139313Ssos * documentation and/or other materials provided with the distribution. 149313Ssos * 3. The name of the author may not be used to endorse or promote products 1597748Sschweikh * derived from this software without specific prior written permission 169313Ssos * 179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279313Ssos * 2850477Speter * $FreeBSD: head/sys/compat/linux/linux_signal.c 104306 2002-10-01 17:15:53Z jmallett $ 299313Ssos */ 309313Ssos 319313Ssos#include <sys/param.h> 329313Ssos#include <sys/systm.h> 3376166Smarkm#include <sys/lock.h> 3476166Smarkm#include <sys/mutex.h> 359313Ssos#include <sys/proc.h> 369313Ssos#include <sys/signalvar.h> 37102814Siedowse#include <sys/syscallsubr.h> 3876166Smarkm#include <sys/sysproto.h> 399313Ssos 4064911Smarcel#include <machine/../linux/linux.h> 4168583Smarcel#include <machine/../linux/linux_proto.h> 4264911Smarcel#include <compat/linux/linux_signal.h> 4364911Smarcel#include <compat/linux/linux_util.h> 449313Ssos 4564911Smarcelvoid 4683221Smarcellinux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 4751793Smarcel{ 4851793Smarcel int b, l; 499313Ssos 5051793Smarcel SIGEMPTYSET(*bss); 5151793Smarcel bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 5251793Smarcel bss->__bits[1] = lss->__bits[1]; 5351793Smarcel for (l = 1; l <= LINUX_SIGTBLSZ; l++) { 5451793Smarcel if (LINUX_SIGISMEMBER(*lss, l)) { 5568201Sobrien#ifdef __alpha__ 5668201Sobrien b = _SIG_IDX(l); 5768201Sobrien#else 5851793Smarcel b = linux_to_bsd_signal[_SIG_IDX(l)]; 5968201Sobrien#endif 6051793Smarcel if (b) 6151793Smarcel SIGADDSET(*bss, b); 6251793Smarcel } 6314331Speter } 649313Ssos} 659313Ssos 6667234Sgallatinvoid 6783221Smarcelbsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 6851793Smarcel{ 6951793Smarcel int b, l; 709313Ssos 7151793Smarcel LINUX_SIGEMPTYSET(*lss); 7251793Smarcel lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 7351793Smarcel lss->__bits[1] = bss->__bits[1]; 7451793Smarcel for (b = 1; b <= LINUX_SIGTBLSZ; b++) { 7551793Smarcel if (SIGISMEMBER(*bss, b)) { 7668201Sobrien#if __alpha__ 7768201Sobrien l = _SIG_IDX(b); 7868201Sobrien#else 7951793Smarcel l = bsd_to_linux_signal[_SIG_IDX(b)]; 8068201Sobrien#endif 8151793Smarcel if (l) 8251793Smarcel LINUX_SIGADDSET(*lss, l); 8351793Smarcel } 8414331Speter } 859313Ssos} 869313Ssos 8714342Speterstatic void 8883221Smarcellinux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa) 8914331Speter{ 9051793Smarcel 9151793Smarcel linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); 9251793Smarcel bsa->sa_handler = lsa->lsa_handler; 9351793Smarcel bsa->sa_flags = 0; 9451793Smarcel if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) 9551793Smarcel bsa->sa_flags |= SA_NOCLDSTOP; 9651793Smarcel if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) 9751793Smarcel bsa->sa_flags |= SA_NOCLDWAIT; 9851793Smarcel if (lsa->lsa_flags & LINUX_SA_SIGINFO) 9951793Smarcel bsa->sa_flags |= SA_SIGINFO; 10051793Smarcel if (lsa->lsa_flags & LINUX_SA_ONSTACK) 10151793Smarcel bsa->sa_flags |= SA_ONSTACK; 10251793Smarcel if (lsa->lsa_flags & LINUX_SA_RESTART) 10351793Smarcel bsa->sa_flags |= SA_RESTART; 10451793Smarcel if (lsa->lsa_flags & LINUX_SA_ONESHOT) 10551793Smarcel bsa->sa_flags |= SA_RESETHAND; 10651793Smarcel if (lsa->lsa_flags & LINUX_SA_NOMASK) 10751793Smarcel bsa->sa_flags |= SA_NODEFER; 10814331Speter} 1099313Ssos 11014342Speterstatic void 11183221Smarcelbsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa) 11214331Speter{ 11351793Smarcel 11451793Smarcel bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); 11551793Smarcel lsa->lsa_handler = bsa->sa_handler; 11651793Smarcel lsa->lsa_restorer = NULL; /* unsupported */ 11751793Smarcel lsa->lsa_flags = 0; 11851793Smarcel if (bsa->sa_flags & SA_NOCLDSTOP) 11951793Smarcel lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; 12051793Smarcel if (bsa->sa_flags & SA_NOCLDWAIT) 12151793Smarcel lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; 12251793Smarcel if (bsa->sa_flags & SA_SIGINFO) 12351793Smarcel lsa->lsa_flags |= LINUX_SA_SIGINFO; 12451793Smarcel if (bsa->sa_flags & SA_ONSTACK) 12551793Smarcel lsa->lsa_flags |= LINUX_SA_ONSTACK; 12651793Smarcel if (bsa->sa_flags & SA_RESTART) 12751793Smarcel lsa->lsa_flags |= LINUX_SA_RESTART; 12851793Smarcel if (bsa->sa_flags & SA_RESETHAND) 12951793Smarcel lsa->lsa_flags |= LINUX_SA_ONESHOT; 13051793Smarcel if (bsa->sa_flags & SA_NODEFER) 13151793Smarcel lsa->lsa_flags |= LINUX_SA_NOMASK; 13214331Speter} 13314331Speter 13464911Smarcelint 13583366Sjulianlinux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa, 13683221Smarcel l_sigaction_t *linux_osa) 13749786Smarcel{ 138102814Siedowse struct sigaction act, oact, *nsa, *osa; 139102814Siedowse int error, sig; 14049786Smarcel 14151793Smarcel if (linux_sig <= 0 || linux_sig > LINUX_NSIG) 14251793Smarcel return (EINVAL); 14349786Smarcel 144102814Siedowse osa = (linux_osa != NULL) ? &oact : NULL; 14551793Smarcel if (linux_nsa != NULL) { 146102814Siedowse nsa = &act; 14753954Smarcel linux_to_bsd_sigaction(linux_nsa, nsa); 148102814Siedowse } else 14951793Smarcel nsa = NULL; 15049786Smarcel 15168201Sobrien#ifndef __alpha__ 15251793Smarcel if (linux_sig <= LINUX_SIGTBLSZ) 153102814Siedowse sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; 15451793Smarcel else 15568201Sobrien#endif 156102814Siedowse sig = linux_sig; 15749786Smarcel 158102814Siedowse error = kern_sigaction(td, sig, nsa, osa, 0); 15949786Smarcel if (error) 16051793Smarcel return (error); 16149786Smarcel 16253954Smarcel if (linux_osa != NULL) 16353954Smarcel bsd_to_linux_sigaction(osa, linux_osa); 16451793Smarcel 16551793Smarcel return (0); 16649786Smarcel} 16749786Smarcel 16868201Sobrien 16968201Sobrien#ifndef __alpha__ 1709313Ssosint 17183366Sjulianlinux_signal(struct thread *td, struct linux_signal_args *args) 17214331Speter{ 17383221Smarcel l_sigaction_t nsa, osa; 17451793Smarcel int error; 1759313Ssos 17614331Speter#ifdef DEBUG 17772543Sjlemon if (ldebug(signal)) 17872543Sjlemon printf(ARGS(signal, "%d, %p"), 17972543Sjlemon args->sig, (void *)args->handler); 18014331Speter#endif 18149786Smarcel 18251793Smarcel nsa.lsa_handler = args->handler; 18351793Smarcel nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 18451793Smarcel LINUX_SIGEMPTYSET(nsa.lsa_mask); 18549786Smarcel 18683366Sjulian error = linux_do_sigaction(td, args->sig, &nsa, &osa); 18783366Sjulian td->td_retval[0] = (int)osa.lsa_handler; 18849786Smarcel 18951793Smarcel return (error); 19049786Smarcel} 19168201Sobrien#endif /*!__alpha__*/ 19249786Smarcel 19349786Smarcelint 19483366Sjulianlinux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args) 19549786Smarcel{ 19683221Smarcel l_sigaction_t nsa, osa; 19751793Smarcel int error; 19849786Smarcel 19949786Smarcel#ifdef DEBUG 20072543Sjlemon if (ldebug(rt_sigaction)) 20172543Sjlemon printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), 20272543Sjlemon (long)args->sig, (void *)args->act, 20372543Sjlemon (void *)args->oact, (long)args->sigsetsize); 20449786Smarcel#endif 20549786Smarcel 20683221Smarcel if (args->sigsetsize != sizeof(l_sigset_t)) 20751793Smarcel return (EINVAL); 20814331Speter 20951793Smarcel if (args->act != NULL) { 21083221Smarcel error = copyin(args->act, &nsa, sizeof(l_sigaction_t)); 21151793Smarcel if (error) 21251793Smarcel return (error); 21351793Smarcel } 21414331Speter 21583366Sjulian error = linux_do_sigaction(td, args->sig, 21651793Smarcel args->act ? &nsa : NULL, 21751793Smarcel args->oact ? &osa : NULL); 21814331Speter 21951793Smarcel if (args->oact != NULL && !error) { 22083221Smarcel error = copyout(&osa, args->oact, sizeof(l_sigaction_t)); 22151793Smarcel } 22249786Smarcel 22351793Smarcel return (error); 22414331Speter} 22514331Speter 22649786Smarcelstatic int 22783366Sjulianlinux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new, 22883221Smarcel l_sigset_t *old) 22949786Smarcel{ 23070061Sjhb int error; 23151793Smarcel sigset_t mask; 23283366Sjulian struct proc *p = td->td_proc; 23314331Speter 23451793Smarcel error = 0; 23583366Sjulian td->td_retval[0] = 0; 23649786Smarcel 23770061Sjhb PROC_LOCK(p); 23851793Smarcel if (old != NULL) 23951793Smarcel bsd_to_linux_sigset(&p->p_sigmask, old); 24049786Smarcel 24151793Smarcel if (new != NULL) { 24251793Smarcel linux_to_bsd_sigset(new, &mask); 24349786Smarcel 24451793Smarcel switch (how) { 24551793Smarcel case LINUX_SIG_BLOCK: 24651793Smarcel SIGSETOR(p->p_sigmask, mask); 24751793Smarcel SIG_CANTMASK(p->p_sigmask); 24851793Smarcel break; 24951793Smarcel case LINUX_SIG_UNBLOCK: 25051793Smarcel SIGSETNAND(p->p_sigmask, mask); 25193793Sbde signotify(p); 25251793Smarcel break; 25351793Smarcel case LINUX_SIG_SETMASK: 25451793Smarcel p->p_sigmask = mask; 25551793Smarcel SIG_CANTMASK(p->p_sigmask); 25693793Sbde signotify(p); 25751793Smarcel break; 25851793Smarcel default: 25951793Smarcel error = EINVAL; 26051793Smarcel break; 26151793Smarcel } 26249786Smarcel } 26370061Sjhb PROC_UNLOCK(p); 26449786Smarcel 26551793Smarcel return (error); 26649786Smarcel} 26749786Smarcel 26868201Sobrien#ifndef __alpha__ 2699313Ssosint 27083366Sjulianlinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args) 2719313Ssos{ 27283221Smarcel l_osigset_t mask; 27383221Smarcel l_sigset_t set, oset; 27451793Smarcel int error; 2759313Ssos 2769313Ssos#ifdef DEBUG 27772543Sjlemon if (ldebug(sigprocmask)) 27872543Sjlemon printf(ARGS(sigprocmask, "%d, *, *"), args->how); 2799313Ssos#endif 28014331Speter 28151793Smarcel if (args->mask != NULL) { 28283221Smarcel error = copyin(args->mask, &mask, sizeof(l_osigset_t)); 28351793Smarcel if (error) 28451793Smarcel return (error); 28551793Smarcel LINUX_SIGEMPTYSET(set); 28651793Smarcel set.__bits[0] = mask; 28751793Smarcel } 28814331Speter 28983366Sjulian error = linux_do_sigprocmask(td, args->how, 29051793Smarcel args->mask ? &set : NULL, 29151793Smarcel args->omask ? &oset : NULL); 29249786Smarcel 29351793Smarcel if (args->omask != NULL && !error) { 29451793Smarcel mask = oset.__bits[0]; 29583221Smarcel error = copyout(&mask, args->omask, sizeof(l_osigset_t)); 29651793Smarcel } 29749786Smarcel 29851793Smarcel return (error); 29949786Smarcel} 30068201Sobrien#endif /*!__alpha__*/ 30149786Smarcel 30249786Smarcelint 30383366Sjulianlinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args) 30449786Smarcel{ 30583221Smarcel l_sigset_t set, oset; 30651793Smarcel int error; 30749786Smarcel 30849786Smarcel#ifdef DEBUG 30972543Sjlemon if (ldebug(rt_sigprocmask)) 31072543Sjlemon printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 31172543Sjlemon args->how, (void *)args->mask, 31272543Sjlemon (void *)args->omask, (long)args->sigsetsize); 31349786Smarcel#endif 31449786Smarcel 31583221Smarcel if (args->sigsetsize != sizeof(l_sigset_t)) 31651793Smarcel return EINVAL; 31749786Smarcel 31851793Smarcel if (args->mask != NULL) { 31983221Smarcel error = copyin(args->mask, &set, sizeof(l_sigset_t)); 32051793Smarcel if (error) 32151793Smarcel return (error); 32251793Smarcel } 32349786Smarcel 32483366Sjulian error = linux_do_sigprocmask(td, args->how, 32551793Smarcel args->mask ? &set : NULL, 32651793Smarcel args->omask ? &oset : NULL); 3279313Ssos 32851793Smarcel if (args->omask != NULL && !error) { 32983221Smarcel error = copyout(&oset, args->omask, sizeof(l_sigset_t)); 33051793Smarcel } 33149786Smarcel 33251793Smarcel return (error); 3339313Ssos} 3349313Ssos 33568201Sobrien#ifndef __alpha__ 3369313Ssosint 33783366Sjulianlinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args) 3389313Ssos{ 33983366Sjulian struct proc *p = td->td_proc; 34083221Smarcel l_sigset_t mask; 34151793Smarcel 3429313Ssos#ifdef DEBUG 34383221Smarcel if (ldebug(sgetmask)) 34483221Smarcel printf(ARGS(sgetmask, "")); 3459313Ssos#endif 34651793Smarcel 34770061Sjhb PROC_LOCK(p); 34851793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &mask); 34970061Sjhb PROC_UNLOCK(p); 35083366Sjulian td->td_retval[0] = mask.__bits[0]; 35151793Smarcel return (0); 3529313Ssos} 3539313Ssos 3549313Ssosint 35583366Sjulianlinux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) 3569313Ssos{ 35783366Sjulian struct proc *p = td->td_proc; 35883221Smarcel l_sigset_t lset; 35951793Smarcel sigset_t bset; 3609313Ssos 3619313Ssos#ifdef DEBUG 36283221Smarcel if (ldebug(ssetmask)) 36383221Smarcel printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); 3649313Ssos#endif 36514331Speter 36670061Sjhb PROC_LOCK(p); 36751793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &lset); 36883366Sjulian td->td_retval[0] = lset.__bits[0]; 36951793Smarcel LINUX_SIGEMPTYSET(lset); 37051793Smarcel lset.__bits[0] = args->mask; 37151793Smarcel linux_to_bsd_sigset(&lset, &bset); 37251793Smarcel p->p_sigmask = bset; 37351793Smarcel SIG_CANTMASK(p->p_sigmask); 37493793Sbde signotify(p); 37570061Sjhb PROC_UNLOCK(p); 37651793Smarcel return (0); 3779313Ssos} 3789313Ssos 3799313Ssosint 38083366Sjulianlinux_sigpending(struct thread *td, struct linux_sigpending_args *args) 3819313Ssos{ 38283366Sjulian struct proc *p = td->td_proc; 38351793Smarcel sigset_t bset; 38483221Smarcel l_sigset_t lset; 38583221Smarcel l_osigset_t mask; 3869313Ssos 3879313Ssos#ifdef DEBUG 38872543Sjlemon if (ldebug(sigpending)) 38972543Sjlemon printf(ARGS(sigpending, "*")); 3909313Ssos#endif 39151793Smarcel 39270061Sjhb PROC_LOCK(p); 393104306Sjmallett bset = p->p_siglist; 39451793Smarcel SIGSETAND(bset, p->p_sigmask); 39551793Smarcel bsd_to_linux_sigset(&bset, &lset); 39670061Sjhb PROC_UNLOCK(p); 39751793Smarcel mask = lset.__bits[0]; 39851793Smarcel return (copyout(&mask, args->mask, sizeof(mask))); 3999313Ssos} 40068201Sobrien#endif /*!__alpha__*/ 4019313Ssos 4029313Ssosint 40383366Sjulianlinux_kill(struct thread *td, struct linux_kill_args *args) 4049313Ssos{ 40551793Smarcel struct kill_args /* { 40651793Smarcel int pid; 40751793Smarcel int signum; 40851793Smarcel } */ tmp; 4099313Ssos 4109313Ssos#ifdef DEBUG 41172543Sjlemon if (ldebug(kill)) 41272543Sjlemon printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 4139313Ssos#endif 41451793Smarcel 41551793Smarcel /* 41651793Smarcel * Allow signal 0 as a means to check for privileges 41751793Smarcel */ 41851793Smarcel if (args->signum < 0 || args->signum > LINUX_NSIG) 41951793Smarcel return EINVAL; 42051793Smarcel 42168201Sobrien#ifndef __alpha__ 42251793Smarcel if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 42351793Smarcel tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 42451793Smarcel else 42568201Sobrien#endif 42651793Smarcel tmp.signum = args->signum; 42751793Smarcel 42851793Smarcel tmp.pid = args->pid; 42983366Sjulian return (kill(td, &tmp)); 4309313Ssos} 431