linux_signal.c revision 113859
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 113859 2003-04-22 18:23:49Z jhb $ 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{ 230113859Sjhb sigset_t omask, nmask; 231113859Sjhb sigset_t *nmaskp; 23270061Sjhb int error; 23314331Speter 23483366Sjulian td->td_retval[0] = 0; 23549786Smarcel 23651793Smarcel if (new != NULL) { 237113859Sjhb linux_to_bsd_sigset(new, &nmask); 238113859Sjhb nmaskp = &nmask; 239113859Sjhb } else 240113859Sjhb nmaskp = NULL; 24149786Smarcel 242113859Sjhb /* Linux sigprocmask flag values are one less than FreeBSD values. */ 243113859Sjhb error = kern_sigprocmask(td, how + 1, nmaskp, &omask, 0); 244113859Sjhb if (error != 0 && old != NULL) 245113859Sjhb bsd_to_linux_sigset(&omask, old); 24649786Smarcel 24751793Smarcel return (error); 24849786Smarcel} 24949786Smarcel 25068201Sobrien#ifndef __alpha__ 2519313Ssosint 25283366Sjulianlinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args) 2539313Ssos{ 25483221Smarcel l_osigset_t mask; 25583221Smarcel l_sigset_t set, oset; 25651793Smarcel int error; 2579313Ssos 2589313Ssos#ifdef DEBUG 25972543Sjlemon if (ldebug(sigprocmask)) 26072543Sjlemon printf(ARGS(sigprocmask, "%d, *, *"), args->how); 2619313Ssos#endif 26214331Speter 26351793Smarcel if (args->mask != NULL) { 26483221Smarcel error = copyin(args->mask, &mask, sizeof(l_osigset_t)); 26551793Smarcel if (error) 26651793Smarcel return (error); 26751793Smarcel LINUX_SIGEMPTYSET(set); 26851793Smarcel set.__bits[0] = mask; 26951793Smarcel } 27014331Speter 27183366Sjulian error = linux_do_sigprocmask(td, args->how, 27251793Smarcel args->mask ? &set : NULL, 27351793Smarcel args->omask ? &oset : NULL); 27449786Smarcel 27551793Smarcel if (args->omask != NULL && !error) { 27651793Smarcel mask = oset.__bits[0]; 27783221Smarcel error = copyout(&mask, args->omask, sizeof(l_osigset_t)); 27851793Smarcel } 27949786Smarcel 28051793Smarcel return (error); 28149786Smarcel} 28268201Sobrien#endif /*!__alpha__*/ 28349786Smarcel 28449786Smarcelint 28583366Sjulianlinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args) 28649786Smarcel{ 28783221Smarcel l_sigset_t set, oset; 28851793Smarcel int error; 28949786Smarcel 29049786Smarcel#ifdef DEBUG 29172543Sjlemon if (ldebug(rt_sigprocmask)) 29272543Sjlemon printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 29372543Sjlemon args->how, (void *)args->mask, 29472543Sjlemon (void *)args->omask, (long)args->sigsetsize); 29549786Smarcel#endif 29649786Smarcel 29783221Smarcel if (args->sigsetsize != sizeof(l_sigset_t)) 29851793Smarcel return EINVAL; 29949786Smarcel 30051793Smarcel if (args->mask != NULL) { 30183221Smarcel error = copyin(args->mask, &set, sizeof(l_sigset_t)); 30251793Smarcel if (error) 30351793Smarcel return (error); 30451793Smarcel } 30549786Smarcel 30683366Sjulian error = linux_do_sigprocmask(td, args->how, 30751793Smarcel args->mask ? &set : NULL, 30851793Smarcel args->omask ? &oset : NULL); 3099313Ssos 31051793Smarcel if (args->omask != NULL && !error) { 31183221Smarcel error = copyout(&oset, args->omask, sizeof(l_sigset_t)); 31251793Smarcel } 31349786Smarcel 31451793Smarcel return (error); 3159313Ssos} 3169313Ssos 31768201Sobrien#ifndef __alpha__ 3189313Ssosint 31983366Sjulianlinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args) 3209313Ssos{ 32183366Sjulian struct proc *p = td->td_proc; 32283221Smarcel l_sigset_t mask; 32351793Smarcel 3249313Ssos#ifdef DEBUG 32583221Smarcel if (ldebug(sgetmask)) 32683221Smarcel printf(ARGS(sgetmask, "")); 3279313Ssos#endif 32851793Smarcel 32970061Sjhb PROC_LOCK(p); 330112888Sjeff bsd_to_linux_sigset(&td->td_sigmask, &mask); 33170061Sjhb PROC_UNLOCK(p); 33283366Sjulian td->td_retval[0] = mask.__bits[0]; 33351793Smarcel return (0); 3349313Ssos} 3359313Ssos 3369313Ssosint 33783366Sjulianlinux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) 3389313Ssos{ 33983366Sjulian struct proc *p = td->td_proc; 34083221Smarcel l_sigset_t lset; 34151793Smarcel sigset_t bset; 3429313Ssos 3439313Ssos#ifdef DEBUG 34483221Smarcel if (ldebug(ssetmask)) 34583221Smarcel printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); 3469313Ssos#endif 34714331Speter 34870061Sjhb PROC_LOCK(p); 349112888Sjeff bsd_to_linux_sigset(&td->td_sigmask, &lset); 35083366Sjulian td->td_retval[0] = lset.__bits[0]; 35151793Smarcel LINUX_SIGEMPTYSET(lset); 35251793Smarcel lset.__bits[0] = args->mask; 35351793Smarcel linux_to_bsd_sigset(&lset, &bset); 354112888Sjeff td->td_sigmask = bset; 355112888Sjeff SIG_CANTMASK(td->td_sigmask); 356112888Sjeff signotify(td); 35770061Sjhb PROC_UNLOCK(p); 35851793Smarcel return (0); 3599313Ssos} 3609313Ssos 361110980Stjr/* 362110980Stjr * MPSAFE 363110980Stjr */ 3649313Ssosint 36583366Sjulianlinux_sigpending(struct thread *td, struct linux_sigpending_args *args) 3669313Ssos{ 36783366Sjulian struct proc *p = td->td_proc; 36851793Smarcel sigset_t bset; 36983221Smarcel l_sigset_t lset; 37083221Smarcel l_osigset_t mask; 3719313Ssos 3729313Ssos#ifdef DEBUG 37372543Sjlemon if (ldebug(sigpending)) 37472543Sjlemon printf(ARGS(sigpending, "*")); 3759313Ssos#endif 37651793Smarcel 37770061Sjhb PROC_LOCK(p); 378104306Sjmallett bset = p->p_siglist; 379112888Sjeff SIGSETOR(bset, td->td_siglist); 380112888Sjeff SIGSETAND(bset, td->td_sigmask); 381113615Sjhb PROC_UNLOCK(p); 38251793Smarcel bsd_to_linux_sigset(&bset, &lset); 38351793Smarcel mask = lset.__bits[0]; 38451793Smarcel return (copyout(&mask, args->mask, sizeof(mask))); 3859313Ssos} 38668201Sobrien#endif /*!__alpha__*/ 3879313Ssos 3889313Ssosint 38983366Sjulianlinux_kill(struct thread *td, struct linux_kill_args *args) 3909313Ssos{ 39151793Smarcel struct kill_args /* { 39251793Smarcel int pid; 39351793Smarcel int signum; 39451793Smarcel } */ tmp; 3959313Ssos 3969313Ssos#ifdef DEBUG 39772543Sjlemon if (ldebug(kill)) 39872543Sjlemon printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 3999313Ssos#endif 40051793Smarcel 40151793Smarcel /* 40251793Smarcel * Allow signal 0 as a means to check for privileges 40351793Smarcel */ 40451793Smarcel if (args->signum < 0 || args->signum > LINUX_NSIG) 40551793Smarcel return EINVAL; 40651793Smarcel 40768201Sobrien#ifndef __alpha__ 40851793Smarcel if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 40951793Smarcel tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 41051793Smarcel else 41168201Sobrien#endif 41251793Smarcel tmp.signum = args->signum; 41351793Smarcel 41451793Smarcel tmp.pid = args->pid; 41583366Sjulian return (kill(td, &tmp)); 4169313Ssos} 417