linux_signal.c revision 72543
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 72543 2001-02-16 16:40:43Z jlemon $ 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 18372543Sjlemon if (ldebug(signal)) 18472543Sjlemon printf(ARGS(signal, "%d, %p"), 18572543Sjlemon args->sig, (void *)args->handler); 18614331Speter#endif 18749786Smarcel 18851793Smarcel nsa.lsa_handler = args->handler; 18951793Smarcel nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 19051793Smarcel LINUX_SIGEMPTYSET(nsa.lsa_mask); 19149786Smarcel 19251793Smarcel error = linux_do_sigaction(p, args->sig, &nsa, &osa); 19351793Smarcel p->p_retval[0] = (int)osa.lsa_handler; 19449786Smarcel 19551793Smarcel return (error); 19649786Smarcel} 19768201Sobrien#endif /*!__alpha__*/ 19849786Smarcel 19949786Smarcelint 20049786Smarcellinux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) 20149786Smarcel{ 20251793Smarcel linux_sigaction_t nsa, osa; 20351793Smarcel int error; 20449786Smarcel 20549786Smarcel#ifdef DEBUG 20672543Sjlemon if (ldebug(rt_sigaction)) 20772543Sjlemon printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), 20872543Sjlemon (long)args->sig, (void *)args->act, 20972543Sjlemon (void *)args->oact, (long)args->sigsetsize); 21049786Smarcel#endif 21149786Smarcel 21251793Smarcel if (args->sigsetsize != sizeof(linux_sigset_t)) 21351793Smarcel return (EINVAL); 21414331Speter 21551793Smarcel if (args->act != NULL) { 21651793Smarcel error = copyin(args->act, &nsa, sizeof(linux_sigaction_t)); 21751793Smarcel if (error) 21851793Smarcel return (error); 21951793Smarcel } 22014331Speter 22151793Smarcel error = linux_do_sigaction(p, args->sig, 22251793Smarcel args->act ? &nsa : NULL, 22351793Smarcel args->oact ? &osa : NULL); 22414331Speter 22551793Smarcel if (args->oact != NULL && !error) { 22651793Smarcel error = copyout(&osa, args->oact, sizeof(linux_sigaction_t)); 22751793Smarcel } 22849786Smarcel 22951793Smarcel return (error); 23014331Speter} 23114331Speter 23249786Smarcelstatic int 23349786Smarcellinux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, 23449786Smarcel linux_sigset_t *old) 23549786Smarcel{ 23670061Sjhb int error; 23751793Smarcel sigset_t mask; 23814331Speter 23951793Smarcel error = 0; 24051793Smarcel p->p_retval[0] = 0; 24149786Smarcel 24270061Sjhb PROC_LOCK(p); 24351793Smarcel if (old != NULL) 24451793Smarcel bsd_to_linux_sigset(&p->p_sigmask, old); 24549786Smarcel 24651793Smarcel if (new != NULL) { 24751793Smarcel linux_to_bsd_sigset(new, &mask); 24849786Smarcel 24951793Smarcel switch (how) { 25051793Smarcel case LINUX_SIG_BLOCK: 25151793Smarcel SIGSETOR(p->p_sigmask, mask); 25251793Smarcel SIG_CANTMASK(p->p_sigmask); 25351793Smarcel break; 25451793Smarcel case LINUX_SIG_UNBLOCK: 25551793Smarcel SIGSETNAND(p->p_sigmask, mask); 25651793Smarcel break; 25751793Smarcel case LINUX_SIG_SETMASK: 25851793Smarcel p->p_sigmask = mask; 25951793Smarcel SIG_CANTMASK(p->p_sigmask); 26051793Smarcel break; 26151793Smarcel default: 26251793Smarcel error = EINVAL; 26351793Smarcel break; 26451793Smarcel } 26549786Smarcel } 26670061Sjhb PROC_UNLOCK(p); 26749786Smarcel 26851793Smarcel return (error); 26949786Smarcel} 27049786Smarcel 27168201Sobrien#ifndef __alpha__ 2729313Ssosint 27330994Sphklinux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) 2749313Ssos{ 27551793Smarcel linux_osigset_t mask; 27651793Smarcel linux_sigset_t set, oset; 27751793Smarcel int error; 2789313Ssos 2799313Ssos#ifdef DEBUG 28072543Sjlemon if (ldebug(sigprocmask)) 28172543Sjlemon printf(ARGS(sigprocmask, "%d, *, *"), args->how); 2829313Ssos#endif 28314331Speter 28451793Smarcel if (args->mask != NULL) { 28551793Smarcel error = copyin(args->mask, &mask, sizeof(linux_osigset_t)); 28651793Smarcel if (error) 28751793Smarcel return (error); 28851793Smarcel LINUX_SIGEMPTYSET(set); 28951793Smarcel set.__bits[0] = mask; 29051793Smarcel } 29114331Speter 29251793Smarcel error = linux_do_sigprocmask(p, args->how, 29351793Smarcel args->mask ? &set : NULL, 29451793Smarcel args->omask ? &oset : NULL); 29549786Smarcel 29651793Smarcel if (args->omask != NULL && !error) { 29751793Smarcel mask = oset.__bits[0]; 29851793Smarcel error = copyout(&mask, args->omask, sizeof(linux_osigset_t)); 29951793Smarcel } 30049786Smarcel 30151793Smarcel return (error); 30249786Smarcel} 30368201Sobrien#endif /*!__alpha__*/ 30449786Smarcel 30549786Smarcelint 30649786Smarcellinux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) 30749786Smarcel{ 30851793Smarcel linux_sigset_t set, oset; 30951793Smarcel int error; 31049786Smarcel 31149786Smarcel#ifdef DEBUG 31272543Sjlemon if (ldebug(rt_sigprocmask)) 31372543Sjlemon printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 31472543Sjlemon args->how, (void *)args->mask, 31572543Sjlemon (void *)args->omask, (long)args->sigsetsize); 31649786Smarcel#endif 31749786Smarcel 31851793Smarcel if (args->sigsetsize != sizeof(linux_sigset_t)) 31951793Smarcel return EINVAL; 32049786Smarcel 32151793Smarcel if (args->mask != NULL) { 32251793Smarcel error = copyin(args->mask, &set, sizeof(linux_sigset_t)); 32351793Smarcel if (error) 32451793Smarcel return (error); 32551793Smarcel } 32649786Smarcel 32751793Smarcel error = linux_do_sigprocmask(p, args->how, 32851793Smarcel args->mask ? &set : NULL, 32951793Smarcel args->omask ? &oset : NULL); 3309313Ssos 33151793Smarcel if (args->omask != NULL && !error) { 33251793Smarcel error = copyout(&oset, args->omask, sizeof(linux_sigset_t)); 33351793Smarcel } 33449786Smarcel 33551793Smarcel return (error); 3369313Ssos} 3379313Ssos 33868201Sobrien#ifndef __alpha__ 3399313Ssosint 34030994Sphklinux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) 3419313Ssos{ 34251793Smarcel linux_sigset_t mask; 34351793Smarcel 3449313Ssos#ifdef DEBUG 34572543Sjlemon if (ldebug(siggetmask)) 34672543Sjlemon printf(ARGS(siggetmask, "")); 3479313Ssos#endif 34851793Smarcel 34970061Sjhb PROC_LOCK(p); 35051793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &mask); 35170061Sjhb PROC_UNLOCK(p); 35251793Smarcel p->p_retval[0] = mask.__bits[0]; 35351793Smarcel return (0); 3549313Ssos} 3559313Ssos 3569313Ssosint 35730994Sphklinux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args) 3589313Ssos{ 35951793Smarcel linux_sigset_t lset; 36051793Smarcel sigset_t bset; 3619313Ssos 3629313Ssos#ifdef DEBUG 36372543Sjlemon if (ldebug(sigsetmask)) 36472543Sjlemon printf(ARGS(sigsetmask, "%08lx"), (unsigned long)args->mask); 3659313Ssos#endif 36614331Speter 36770061Sjhb PROC_LOCK(p); 36851793Smarcel bsd_to_linux_sigset(&p->p_sigmask, &lset); 36951793Smarcel p->p_retval[0] = lset.__bits[0]; 37051793Smarcel LINUX_SIGEMPTYSET(lset); 37151793Smarcel lset.__bits[0] = args->mask; 37251793Smarcel linux_to_bsd_sigset(&lset, &bset); 37351793Smarcel p->p_sigmask = bset; 37451793Smarcel SIG_CANTMASK(p->p_sigmask); 37570061Sjhb PROC_UNLOCK(p); 37651793Smarcel return (0); 3779313Ssos} 3789313Ssos 3799313Ssosint 38030994Sphklinux_sigpending(struct proc *p, struct linux_sigpending_args *args) 3819313Ssos{ 38251793Smarcel sigset_t bset; 38351793Smarcel linux_sigset_t lset; 38451793Smarcel linux_osigset_t mask; 3859313Ssos 3869313Ssos#ifdef DEBUG 38772543Sjlemon if (ldebug(sigpending)) 38872543Sjlemon printf(ARGS(sigpending, "*")); 3899313Ssos#endif 39051793Smarcel 39170061Sjhb PROC_LOCK(p); 39251793Smarcel bset = p->p_siglist; 39351793Smarcel SIGSETAND(bset, p->p_sigmask); 39451793Smarcel bsd_to_linux_sigset(&bset, &lset); 39570061Sjhb PROC_UNLOCK(p); 39651793Smarcel mask = lset.__bits[0]; 39751793Smarcel return (copyout(&mask, args->mask, sizeof(mask))); 3989313Ssos} 39968201Sobrien#endif /*!__alpha__*/ 4009313Ssos 4019313Ssosint 40230994Sphklinux_kill(struct proc *p, struct linux_kill_args *args) 4039313Ssos{ 40451793Smarcel struct kill_args /* { 40551793Smarcel int pid; 40651793Smarcel int signum; 40751793Smarcel } */ tmp; 4089313Ssos 4099313Ssos#ifdef DEBUG 41072543Sjlemon if (ldebug(kill)) 41172543Sjlemon printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 4129313Ssos#endif 41351793Smarcel 41451793Smarcel /* 41551793Smarcel * Allow signal 0 as a means to check for privileges 41651793Smarcel */ 41751793Smarcel if (args->signum < 0 || args->signum > LINUX_NSIG) 41851793Smarcel return EINVAL; 41951793Smarcel 42068201Sobrien#ifndef __alpha__ 42151793Smarcel if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 42251793Smarcel tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 42351793Smarcel else 42468201Sobrien#endif 42551793Smarcel tmp.signum = args->signum; 42651793Smarcel 42751793Smarcel tmp.pid = args->pid; 42851793Smarcel return (kill(p, &tmp)); 4299313Ssos} 430