linux_signal.c revision 70061
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 159313Ssos * derived from this software withough 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 70061 2000-12-15 19:41:27Z jhb $ 299313Ssos */ 309313Ssos 319313Ssos#include <sys/param.h> 329313Ssos#include <sys/systm.h> 3312458Sbde#include <sys/sysproto.h> 349313Ssos#include <sys/proc.h> 359313Ssos#include <sys/signalvar.h> 369313Ssos 3764911Smarcel#include <machine/../linux/linux.h> 3868583Smarcel#include <machine/../linux/linux_proto.h> 3964911Smarcel#include <compat/linux/linux_signal.h> 4064911Smarcel#include <compat/linux/linux_util.h> 419313Ssos 4264911Smarcelvoid 4351793Smarcellinux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss) 4451793Smarcel{ 4551793Smarcel int b, l; 469313Ssos 4751793Smarcel SIGEMPTYSET(*bss); 4851793Smarcel bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 4951793Smarcel bss->__bits[1] = lss->__bits[1]; 5051793Smarcel for (l = 1; l <= LINUX_SIGTBLSZ; l++) { 5151793Smarcel if (LINUX_SIGISMEMBER(*lss, l)) { 5268201Sobrien#ifdef __alpha__ 5368201Sobrien b = _SIG_IDX(l); 5468201Sobrien#else 5551793Smarcel b = linux_to_bsd_signal[_SIG_IDX(l)]; 5668201Sobrien#endif 5751793Smarcel if (b) 5851793Smarcel SIGADDSET(*bss, b); 5951793Smarcel } 6014331Speter } 619313Ssos} 629313Ssos 6367234Sgallatinvoid 6451793Smarcelbsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) 6551793Smarcel{ 6651793Smarcel int b, l; 679313Ssos 6851793Smarcel LINUX_SIGEMPTYSET(*lss); 6951793Smarcel lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 7051793Smarcel lss->__bits[1] = bss->__bits[1]; 7151793Smarcel for (b = 1; b <= LINUX_SIGTBLSZ; b++) { 7251793Smarcel if (SIGISMEMBER(*bss, b)) { 7368201Sobrien#if __alpha__ 7468201Sobrien l = _SIG_IDX(b); 7568201Sobrien#else 7651793Smarcel l = bsd_to_linux_signal[_SIG_IDX(b)]; 7768201Sobrien#endif 7851793Smarcel if (l) 7951793Smarcel LINUX_SIGADDSET(*lss, l); 8051793Smarcel } 8114331Speter } 829313Ssos} 839313Ssos 8414342Speterstatic void 8514331Speterlinux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) 8614331Speter{ 8751793Smarcel 8851793Smarcel linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); 8951793Smarcel bsa->sa_handler = lsa->lsa_handler; 9051793Smarcel bsa->sa_flags = 0; 9151793Smarcel if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) 9251793Smarcel bsa->sa_flags |= SA_NOCLDSTOP; 9351793Smarcel if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) 9451793Smarcel bsa->sa_flags |= SA_NOCLDWAIT; 9551793Smarcel if (lsa->lsa_flags & LINUX_SA_SIGINFO) 9651793Smarcel bsa->sa_flags |= SA_SIGINFO; 9751793Smarcel if (lsa->lsa_flags & LINUX_SA_ONSTACK) 9851793Smarcel bsa->sa_flags |= SA_ONSTACK; 9951793Smarcel if (lsa->lsa_flags & LINUX_SA_RESTART) 10051793Smarcel bsa->sa_flags |= SA_RESTART; 10151793Smarcel if (lsa->lsa_flags & LINUX_SA_ONESHOT) 10251793Smarcel bsa->sa_flags |= SA_RESETHAND; 10351793Smarcel if (lsa->lsa_flags & LINUX_SA_NOMASK) 10451793Smarcel bsa->sa_flags |= SA_NODEFER; 10514331Speter} 1069313Ssos 10714342Speterstatic void 10814331Speterbsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) 10914331Speter{ 11051793Smarcel 11151793Smarcel bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); 11251793Smarcel lsa->lsa_handler = bsa->sa_handler; 11351793Smarcel lsa->lsa_restorer = NULL; /* unsupported */ 11451793Smarcel lsa->lsa_flags = 0; 11551793Smarcel if (bsa->sa_flags & SA_NOCLDSTOP) 11651793Smarcel lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; 11751793Smarcel if (bsa->sa_flags & SA_NOCLDWAIT) 11851793Smarcel lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; 11951793Smarcel if (bsa->sa_flags & SA_SIGINFO) 12051793Smarcel lsa->lsa_flags |= LINUX_SA_SIGINFO; 12151793Smarcel if (bsa->sa_flags & SA_ONSTACK) 12251793Smarcel lsa->lsa_flags |= LINUX_SA_ONSTACK; 12351793Smarcel if (bsa->sa_flags & SA_RESTART) 12451793Smarcel lsa->lsa_flags |= LINUX_SA_RESTART; 12551793Smarcel if (bsa->sa_flags & SA_RESETHAND) 12651793Smarcel lsa->lsa_flags |= LINUX_SA_ONESHOT; 12751793Smarcel if (bsa->sa_flags & SA_NODEFER) 12851793Smarcel lsa->lsa_flags |= LINUX_SA_NOMASK; 12914331Speter} 13014331Speter 13164911Smarcelint 13249786Smarcellinux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa, 13349786Smarcel linux_sigaction_t *linux_osa) 13449786Smarcel{ 13553954Smarcel struct sigaction *nsa, *osa; 13651793Smarcel struct sigaction_args sa_args; 13751793Smarcel int error; 13851793Smarcel caddr_t sg = stackgap_init(); 13949786Smarcel 14051793Smarcel if (linux_sig <= 0 || linux_sig > LINUX_NSIG) 14151793Smarcel return (EINVAL); 14249786Smarcel 14351793Smarcel if (linux_osa != NULL) 14451793Smarcel osa = stackgap_alloc(&sg, sizeof(struct sigaction)); 14551793Smarcel else 14651793Smarcel osa = NULL; 14749786Smarcel 14851793Smarcel if (linux_nsa != NULL) { 14951793Smarcel nsa = stackgap_alloc(&sg, sizeof(struct sigaction)); 15053954Smarcel linux_to_bsd_sigaction(linux_nsa, nsa); 15151793Smarcel } 15251793Smarcel else 15351793Smarcel nsa = NULL; 15449786Smarcel 15568201Sobrien#ifndef __alpha__ 15651793Smarcel if (linux_sig <= LINUX_SIGTBLSZ) 15751793Smarcel sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; 15851793Smarcel else 15968201Sobrien#endif 16051793Smarcel sa_args.sig = linux_sig; 16149786Smarcel 16251793Smarcel sa_args.act = nsa; 16351793Smarcel sa_args.oact = osa; 16451793Smarcel error = sigaction(p, &sa_args); 16549786Smarcel if (error) 16651793Smarcel return (error); 16749786Smarcel 16853954Smarcel if (linux_osa != NULL) 16953954Smarcel bsd_to_linux_sigaction(osa, linux_osa); 17051793Smarcel 17151793Smarcel return (0); 17249786Smarcel} 17349786Smarcel 17468201Sobrien 17568201Sobrien#ifndef __alpha__ 1769313Ssosint 17730994Sphklinux_signal(struct proc *p, struct linux_signal_args *args) 17814331Speter{ 17951793Smarcel linux_sigaction_t nsa, osa; 18051793Smarcel int error; 1819313Ssos 18214331Speter#ifdef DEBUG 18351793Smarcel printf("Linux-emul(%ld): signal(%d, %p)\n", 18451793Smarcel (long)p->p_pid, args->sig, (void *)args->handler); 18514331Speter#endif 18649786Smarcel 18751793Smarcel nsa.lsa_handler = args->handler; 18851793Smarcel nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 18951793Smarcel LINUX_SIGEMPTYSET(nsa.lsa_mask); 19049786Smarcel 19151793Smarcel error = linux_do_sigaction(p, args->sig, &nsa, &osa); 19251793Smarcel p->p_retval[0] = (int)osa.lsa_handler; 19349786Smarcel 19451793Smarcel return (error); 19549786Smarcel} 19668201Sobrien#endif /*!__alpha__*/ 19749786Smarcel 19849786Smarcelint 19949786Smarcellinux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) 20049786Smarcel{ 20151793Smarcel linux_sigaction_t nsa, osa; 20251793Smarcel int error; 20349786Smarcel 20449786Smarcel#ifdef DEBUG 20568201Sobrien printf("Linux-emul(%ld): rt_sigaction(%ld, %p, %p, %ld)\n", 20668201Sobrien (long)p->p_pid, (long)args->sig, (void *)args->act, 20768201Sobrien (void *)args->oact, (long)args->sigsetsize); 20849786Smarcel#endif 20949786Smarcel 21051793Smarcel if (args->sigsetsize != sizeof(linux_sigset_t)) 21151793Smarcel return (EINVAL); 21214331Speter 21351793Smarcel if (args->act != NULL) { 21451793Smarcel error = copyin(args->act, &nsa, sizeof(linux_sigaction_t)); 21551793Smarcel if (error) 21651793Smarcel return (error); 21751793Smarcel } 21814331Speter 21951793Smarcel error = linux_do_sigaction(p, args->sig, 22051793Smarcel args->act ? &nsa : NULL, 22151793Smarcel args->oact ? &osa : NULL); 22214331Speter 22351793Smarcel if (args->oact != NULL && !error) { 22451793Smarcel error = copyout(&osa, args->oact, sizeof(linux_sigaction_t)); 22551793Smarcel } 22649786Smarcel 22751793Smarcel return (error); 22814331Speter} 22914331Speter 23049786Smarcelstatic int 23149786Smarcellinux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, 23249786Smarcel linux_sigset_t *old) 23349786Smarcel{ 23470061Sjhb int error; 23551793Smarcel sigset_t mask; 23614331Speter 23751793Smarcel error = 0; 23851793Smarcel p->p_retval[0] = 0; 23949786Smarcel 24070061Sjhb PROC_LOCK(p); 24151793Smarcel if (old != NULL) 24251793Smarcel bsd_to_linux_sigset(&p->p_sigmask, old); 24349786Smarcel 24451793Smarcel if (new != NULL) { 24551793Smarcel linux_to_bsd_sigset(new, &mask); 24649786Smarcel 24751793Smarcel switch (how) { 24851793Smarcel case LINUX_SIG_BLOCK: 24951793Smarcel SIGSETOR(p->p_sigmask, mask); 25051793Smarcel SIG_CANTMASK(p->p_sigmask); 25151793Smarcel break; 25251793Smarcel case LINUX_SIG_UNBLOCK: 25351793Smarcel SIGSETNAND(p->p_sigmask, mask); 25451793Smarcel break; 25551793Smarcel case LINUX_SIG_SETMASK: 25651793Smarcel p->p_sigmask = mask; 25751793Smarcel SIG_CANTMASK(p->p_sigmask); 25851793Smarcel break; 25951793Smarcel default: 26051793Smarcel error = EINVAL; 26151793Smarcel break; 26251793Smarcel } 26349786Smarcel } 26470061Sjhb PROC_UNLOCK(p); 26549786Smarcel 26651793Smarcel return (error); 26749786Smarcel} 26849786Smarcel 26968201Sobrien#ifndef __alpha__ 2709313Ssosint 27130994Sphklinux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) 2729313Ssos{ 27351793Smarcel linux_osigset_t mask; 27451793Smarcel linux_sigset_t set, oset; 27551793Smarcel int error; 2769313Ssos 2779313Ssos#ifdef DEBUG 27851793Smarcel printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how); 2799313Ssos#endif 28014331Speter 28151793Smarcel if (args->mask != NULL) { 28251793Smarcel error = copyin(args->mask, &mask, sizeof(linux_osigset_t)); 28351793Smarcel if (error) 28451793Smarcel return (error); 28551793Smarcel LINUX_SIGEMPTYSET(set); 28651793Smarcel set.__bits[0] = mask; 28751793Smarcel } 28814331Speter 28951793Smarcel error = linux_do_sigprocmask(p, args->how, 29051793Smarcel args->mask ? &set : NULL, 29151793Smarcel args->omask ? &oset : NULL); 29249786Smarcel 29351793Smarcel if (args->omask != NULL && !error) { 29451793Smarcel mask = oset.__bits[0]; 29551793Smarcel error = copyout(&mask, args->omask, sizeof(linux_osigset_t)); 29651793Smarcel } 29749786Smarcel 29851793Smarcel return (error); 29949786Smarcel} 30068201Sobrien#endif /*!__alpha__*/ 30149786Smarcel 30249786Smarcelint 30349786Smarcellinux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) 30449786Smarcel{ 30551793Smarcel linux_sigset_t set, oset; 30651793Smarcel int error; 30749786Smarcel 30849786Smarcel#ifdef DEBUG 30968201Sobrien printf("Linux-emul(%ld): rt_sigprocmask(%d, %p, %p, %ld)\n", 31051793Smarcel (long)p->p_pid, args->how, (void *)args->mask, 31168201Sobrien (void *)args->omask, (long)args->sigsetsize); 31249786Smarcel#endif 31349786Smarcel 31451793Smarcel if (args->sigsetsize != sizeof(linux_sigset_t)) 31551793Smarcel return EINVAL; 31649786Smarcel 31751793Smarcel if (args->mask != NULL) { 31851793Smarcel error = copyin(args->mask, &set, sizeof(linux_sigset_t)); 31951793Smarcel if (error) 32051793Smarcel return (error); 32151793Smarcel } 32249786Smarcel 32351793Smarcel error = linux_do_sigprocmask(p, args->how, 32451793Smarcel args->mask ? &set : NULL, 32551793Smarcel args->omask ? &oset : NULL); 3269313Ssos 32751793Smarcel if (args->omask != NULL && !error) { 32851793Smarcel error = copyout(&oset, args->omask, sizeof(linux_sigset_t)); 32951793Smarcel } 33049786Smarcel 33151793Smarcel return (error); 3329313Ssos} 3339313Ssos 33468201Sobrien#ifndef __alpha__ 3359313Ssosint 33630994Sphklinux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) 3379313Ssos{ 33851793Smarcel linux_sigset_t mask; 33951793Smarcel 3409313Ssos#ifdef DEBUG 34151793Smarcel printf("Linux-emul(%d): siggetmask()\n", p->p_pid); 3429313Ssos#endif 34351793Smarcel 34470061Sjhb PROC_LOCK(p); 34551793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &mask); 34670061Sjhb PROC_UNLOCK(p); 34751793Smarcel p->p_retval[0] = mask.__bits[0]; 34851793Smarcel return (0); 3499313Ssos} 3509313Ssos 3519313Ssosint 35230994Sphklinux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args) 3539313Ssos{ 35451793Smarcel linux_sigset_t lset; 35551793Smarcel sigset_t bset; 3569313Ssos 3579313Ssos#ifdef DEBUG 35851793Smarcel printf("Linux-emul(%ld): sigsetmask(%08lx)\n", 35951793Smarcel (long)p->p_pid, (unsigned long)args->mask); 3609313Ssos#endif 36114331Speter 36270061Sjhb PROC_LOCK(p); 36351793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &lset); 36451793Smarcel p->p_retval[0] = lset.__bits[0]; 36551793Smarcel LINUX_SIGEMPTYSET(lset); 36651793Smarcel lset.__bits[0] = args->mask; 36751793Smarcel linux_to_bsd_sigset(&lset, &bset); 36851793Smarcel p->p_sigmask = bset; 36951793Smarcel SIG_CANTMASK(p->p_sigmask); 37070061Sjhb PROC_UNLOCK(p); 37151793Smarcel return (0); 3729313Ssos} 3739313Ssos 3749313Ssosint 37530994Sphklinux_sigpending(struct proc *p, struct linux_sigpending_args *args) 3769313Ssos{ 37751793Smarcel sigset_t bset; 37851793Smarcel linux_sigset_t lset; 37951793Smarcel linux_osigset_t mask; 3809313Ssos 3819313Ssos#ifdef DEBUG 38251793Smarcel printf("Linux-emul(%d): sigpending(*)\n", p->p_pid); 3839313Ssos#endif 38451793Smarcel 38570061Sjhb PROC_LOCK(p); 38651793Smarcel bset = p->p_siglist; 38751793Smarcel SIGSETAND(bset, p->p_sigmask); 38851793Smarcel bsd_to_linux_sigset(&bset, &lset); 38970061Sjhb PROC_UNLOCK(p); 39051793Smarcel mask = lset.__bits[0]; 39151793Smarcel return (copyout(&mask, args->mask, sizeof(mask))); 3929313Ssos} 39368201Sobrien#endif /*!__alpha__*/ 3949313Ssos 3959313Ssosint 39630994Sphklinux_kill(struct proc *p, struct linux_kill_args *args) 3979313Ssos{ 39851793Smarcel struct kill_args /* { 39951793Smarcel int pid; 40051793Smarcel int signum; 40151793Smarcel } */ tmp; 4029313Ssos 4039313Ssos#ifdef DEBUG 40451793Smarcel printf("Linux-emul(%d): kill(%d, %d)\n", 40551793Smarcel p->p_pid, args->pid, args->signum); 4069313Ssos#endif 40751793Smarcel 40851793Smarcel /* 40951793Smarcel * Allow signal 0 as a means to check for privileges 41051793Smarcel */ 41151793Smarcel if (args->signum < 0 || args->signum > LINUX_NSIG) 41251793Smarcel return EINVAL; 41351793Smarcel 41468201Sobrien#ifndef __alpha__ 41551793Smarcel if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 41651793Smarcel tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 41751793Smarcel else 41868201Sobrien#endif 41951793Smarcel tmp.signum = args->signum; 42051793Smarcel 42151793Smarcel tmp.pid = args->pid; 42251793Smarcel return (kill(p, &tmp)); 4239313Ssos} 424