diff options
Diffstat (limited to 'sys/i386/linux/linux_signal.c')
-rw-r--r-- | sys/i386/linux/linux_signal.c | 615 |
1 files changed, 334 insertions, 281 deletions
diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c index 9f2200e526a69..39334a746409a 100644 --- a/sys/i386/linux/linux_signal.c +++ b/sys/i386/linux/linux_signal.c @@ -38,382 +38,384 @@ #include <i386/linux/linux_proto.h> #include <i386/linux/linux_util.h> -static sigset_t -linux_to_bsd_sigset(linux_sigset_t mask) { - int b, l; - sigset_t new = 0; - - for (l = 1; l < LINUX_NSIG; l++) { - if (mask & (1 << (l - 1))) { - if ((b = linux_to_bsd_signal[l])) - new |= (1 << (b - 1)); +static void +linux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss) +{ + int b, l; + + SIGEMPTYSET(*bss); + bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); + bss->__bits[1] = lss->__bits[1]; + for (l = 1; l <= LINUX_SIGTBLSZ; l++) { + if (LINUX_SIGISMEMBER(*lss, l)) { + b = linux_to_bsd_signal[_SIG_IDX(l)]; + if (b) + SIGADDSET(*bss, b); + } } - } - return new; } -static linux_sigset_t -bsd_to_linux_sigset(sigset_t mask) { - int b, l; - sigset_t new = 0; - - for (b = 1; b < NSIG; b++) { - if (mask & (1 << (b - 1))) { - if ((l = bsd_to_linux_signal[b])) - new |= (1 << (l - 1)); +static void +bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) +{ + int b, l; + + LINUX_SIGEMPTYSET(*lss); + lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); + lss->__bits[1] = bss->__bits[1]; + for (b = 1; b <= LINUX_SIGTBLSZ; b++) { + if (SIGISMEMBER(*bss, b)) { + l = bsd_to_linux_signal[_SIG_IDX(b)]; + if (l) + LINUX_SIGADDSET(*lss, l); + } } - } - return new; } static void linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) { - bsa->sa_mask = linux_to_bsd_sigset(lsa->lsa_mask); - bsa->sa_handler = lsa->lsa_handler; - bsa->sa_flags = 0; - if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) - bsa->sa_flags |= SA_NOCLDSTOP; - if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) - bsa->sa_flags |= SA_NOCLDWAIT; - if (lsa->lsa_flags & LINUX_SA_SIGINFO) - bsa->sa_flags |= SA_SIGINFO; - if (lsa->lsa_flags & LINUX_SA_ONSTACK) - bsa->sa_flags |= SA_ONSTACK; - if (lsa->lsa_flags & LINUX_SA_RESTART) - bsa->sa_flags |= SA_RESTART; - if (lsa->lsa_flags & LINUX_SA_ONESHOT) - bsa->sa_flags |= SA_RESETHAND; - if (lsa->lsa_flags & LINUX_SA_NOMASK) - bsa->sa_flags |= SA_NODEFER; + + linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); + bsa->sa_handler = lsa->lsa_handler; + bsa->sa_flags = 0; + if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) + bsa->sa_flags |= SA_NOCLDSTOP; + if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) + bsa->sa_flags |= SA_NOCLDWAIT; + if (lsa->lsa_flags & LINUX_SA_SIGINFO) + bsa->sa_flags |= SA_SIGINFO; + if (lsa->lsa_flags & LINUX_SA_ONSTACK) + bsa->sa_flags |= SA_ONSTACK; + if (lsa->lsa_flags & LINUX_SA_RESTART) + bsa->sa_flags |= SA_RESTART; + if (lsa->lsa_flags & LINUX_SA_ONESHOT) + bsa->sa_flags |= SA_RESETHAND; + if (lsa->lsa_flags & LINUX_SA_NOMASK) + bsa->sa_flags |= SA_NODEFER; } static void bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) { - lsa->lsa_handler = bsa->sa_handler; - lsa->lsa_restorer = NULL; /* unsupported */ - lsa->lsa_mask = bsd_to_linux_sigset(bsa->sa_mask); - lsa->lsa_flags = 0; - if (bsa->sa_flags & SA_NOCLDSTOP) - lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; - if (bsa->sa_flags & SA_NOCLDWAIT) - lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; - if (bsa->sa_flags & SA_SIGINFO) - lsa->lsa_flags |= LINUX_SA_SIGINFO; - if (bsa->sa_flags & SA_ONSTACK) - lsa->lsa_flags |= LINUX_SA_ONSTACK; - if (bsa->sa_flags & SA_RESTART) - lsa->lsa_flags |= LINUX_SA_RESTART; - if (bsa->sa_flags & SA_RESETHAND) - lsa->lsa_flags |= LINUX_SA_ONESHOT; - if (bsa->sa_flags & SA_NODEFER) - lsa->lsa_flags |= LINUX_SA_NOMASK; + + bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); + lsa->lsa_handler = bsa->sa_handler; + lsa->lsa_restorer = NULL; /* unsupported */ + lsa->lsa_flags = 0; + if (bsa->sa_flags & SA_NOCLDSTOP) + lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; + if (bsa->sa_flags & SA_NOCLDWAIT) + lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; + if (bsa->sa_flags & SA_SIGINFO) + lsa->lsa_flags |= LINUX_SA_SIGINFO; + if (bsa->sa_flags & SA_ONSTACK) + lsa->lsa_flags |= LINUX_SA_ONSTACK; + if (bsa->sa_flags & SA_RESTART) + lsa->lsa_flags |= LINUX_SA_RESTART; + if (bsa->sa_flags & SA_RESETHAND) + lsa->lsa_flags |= LINUX_SA_ONESHOT; + if (bsa->sa_flags & SA_NODEFER) + lsa->lsa_flags |= LINUX_SA_NOMASK; } static int linux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa, linux_sigaction_t *linux_osa) { - struct sigaction *nsa, *osa, sa; - struct sigaction_args sa_args; - int error; - caddr_t sg = stackgap_init(); - - if (linux_sig <= 0 || linux_sig >= LINUX_NSIG) - return EINVAL; - - if (linux_osa) - osa = stackgap_alloc(&sg, sizeof(struct sigaction)); - else - osa = NULL; - - if (linux_nsa) { - nsa = stackgap_alloc(&sg, sizeof(struct sigaction)); - linux_to_bsd_sigaction(linux_nsa, &sa); - error = copyout(&sa, nsa, sizeof(struct sigaction)); - if (error) - return error; - } - else - nsa = NULL; - - sa_args.signum = linux_to_bsd_signal[linux_sig]; - sa_args.nsa = nsa; - sa_args.osa = osa; - error = sigaction(p, &sa_args); - if (error) - return error; - - if (linux_osa) { - error = copyin(osa, &sa, sizeof(struct sigaction)); + struct sigaction *nsa, *osa, sa; + struct sigaction_args sa_args; + int error; + caddr_t sg = stackgap_init(); + + if (linux_sig <= 0 || linux_sig > LINUX_NSIG) + return (EINVAL); + + if (linux_osa != NULL) + osa = stackgap_alloc(&sg, sizeof(struct sigaction)); + else + osa = NULL; + + if (linux_nsa != NULL) { + nsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + linux_to_bsd_sigaction(linux_nsa, &sa); + error = copyout(&sa, nsa, sizeof(struct sigaction)); + if (error) + return (error); + } + else + nsa = NULL; + + if (linux_sig <= LINUX_SIGTBLSZ) + sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; + else + sa_args.sig = linux_sig; + + sa_args.act = nsa; + sa_args.oact = osa; + error = sigaction(p, &sa_args); if (error) - return error; - bsd_to_linux_sigaction(&sa, linux_osa); - } + return (error); + + if (linux_osa != NULL) { + error = copyin(osa, &sa, sizeof(struct sigaction)); + if (error) + return (error); + bsd_to_linux_sigaction(&sa, linux_osa); + } - return 0; + return (0); } int linux_sigaction(struct proc *p, struct linux_sigaction_args *args) { - linux_sigaction_t nsa, osa; - int error; + linux_osigaction_t osa; + linux_sigaction_t act, oact; + int error; #ifdef DEBUG - printf("Linux-emul(%ld): sigaction(%d, %p, %p)\n", - (long)p->p_pid, args->sig, (void *)args->nsa, (void *)args->osa); + printf("Linux-emul(%ld): sigaction(%d, %p, %p)\n", (long)p->p_pid, + args->sig, (void *)args->nsa, (void *)args->osa); #endif - if (args->nsa) { - error = copyin(args->nsa, &nsa, sizeof(linux_sigaction_t)); - if (error) - return error; - } + if (args->nsa != NULL) { + error = copyin(args->nsa, &osa, sizeof(linux_osigaction_t)); + if (error) + return (error); + act.lsa_handler = osa.lsa_handler; + act.lsa_flags = osa.lsa_flags; + act.lsa_restorer = osa.lsa_restorer; + LINUX_SIGEMPTYSET(act.lsa_mask); + act.lsa_mask.__bits[0] = osa.lsa_mask; + } - error = linux_do_sigaction(p, args->sig, - args->nsa ? &nsa : NULL, - args->osa ? &osa : NULL); - if (error) - return error; + error = linux_do_sigaction(p, args->sig, + args->nsa ? &act : NULL, + args->osa ? &oact : NULL); - if (args->osa) { - error = copyout(&osa, args->osa, sizeof(linux_sigaction_t)); - if (error) - return error; - } + if (args->osa != NULL && !error) { + osa.lsa_handler = oact.lsa_handler; + osa.lsa_flags = oact.lsa_flags; + osa.lsa_restorer = oact.lsa_restorer; + osa.lsa_mask = oact.lsa_mask.__bits[0]; + error = copyout(&osa, args->osa, sizeof(linux_osigaction_t)); + } - return 0; + return (error); } int linux_signal(struct proc *p, struct linux_signal_args *args) { - linux_sigaction_t nsa, osa; - int error; + linux_sigaction_t nsa, osa; + int error; #ifdef DEBUG - printf("Linux-emul(%ld): signal(%d, %p)\n", - (long)p->p_pid, args->sig, (void *)args->handler); + printf("Linux-emul(%ld): signal(%d, %p)\n", + (long)p->p_pid, args->sig, (void *)args->handler); #endif - nsa.lsa_handler = args->handler; - nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; - nsa.lsa_mask = NULL; + nsa.lsa_handler = args->handler; + nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; + LINUX_SIGEMPTYSET(nsa.lsa_mask); - error = linux_do_sigaction(p, args->sig, &nsa, &osa); + error = linux_do_sigaction(p, args->sig, &nsa, &osa); + p->p_retval[0] = (int)osa.lsa_handler; - p->p_retval[0] = (int)osa.lsa_handler; - - return 0; + return (error); } int linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) { - linux_sigaction_t nsa, osa; - linux_new_sigaction_t new_sa; - int error; + linux_sigaction_t nsa, osa; + int error; #ifdef DEBUG - printf("Linux-emul(%ld): rt_sigaction(%d, %p, %p, %d)\n", - (long)p->p_pid, args->sig, (void *)args->act, - (void *)args->oact, args->sigsetsize); + printf("Linux-emul(%ld): rt_sigaction(%d, %p, %p, %d)\n", + (long)p->p_pid, args->sig, (void *)args->act, + (void *)args->oact, args->sigsetsize); #endif - if (args->sigsetsize != sizeof(linux_new_sigset_t)) - return EINVAL; - -#ifdef DEBUG - if (args->sig >= LINUX_NSIG) { - printf("LINUX(%ld): rt_sigaction: 64-bit signal (%d)\n", - (long)p->p_pid, args->sig); - } -#endif + if (args->sigsetsize != sizeof(linux_sigset_t)) + return (EINVAL); - if (args->act) { - error = copyin(args->act, &new_sa, sizeof(linux_new_sigaction_t)); - if (error) - return error; + if (args->act != NULL) { + error = copyin(args->act, &nsa, sizeof(linux_sigaction_t)); + if (error) + return (error); + } - nsa.lsa_handler = new_sa.lsa_handler; - nsa.lsa_mask = new_sa.lsa_mask.sig[0]; - nsa.lsa_flags = new_sa.lsa_flags; - nsa.lsa_restorer = new_sa.lsa_restorer; + error = linux_do_sigaction(p, args->sig, + args->act ? &nsa : NULL, + args->oact ? &osa : NULL); -#ifdef DEBUG - if (new_sa.lsa_mask.sig[1] != 0) - printf("LINUX(%ld): rt_sigaction: sig[1] = 0x%08lx\n", - (long)p->p_pid, new_sa.lsa_mask.sig[1]); -#endif - } - - error = linux_do_sigaction(p, args->sig, - args->act ? &nsa : NULL, - args->oact ? &osa : NULL); - if (error) - return error; - - if (args->oact) { - new_sa.lsa_handler = osa.lsa_handler; - new_sa.lsa_flags = osa.lsa_flags; - new_sa.lsa_restorer = osa.lsa_restorer; - new_sa.lsa_mask.sig[0] = osa.lsa_mask; - new_sa.lsa_mask.sig[1] = 0; - error = copyout(&osa, args->oact, sizeof(linux_new_sigaction_t)); - if (error) - return error; - } + if (args->oact != NULL && !error) { + error = copyout(&osa, args->oact, sizeof(linux_sigaction_t)); + } - return 0; + return (error); } static int linux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, linux_sigset_t *old) { - int error = 0, s; - sigset_t mask; - - p->p_retval[0] = 0; - - if (old != NULL) - *old = bsd_to_linux_sigset(p->p_sigmask); - - if (new != NULL) { - mask = linux_to_bsd_sigset(*new); - - s = splhigh(); - - switch (how) { - case LINUX_SIG_BLOCK: - p->p_sigmask |= (mask & ~sigcantmask); - break; - case LINUX_SIG_UNBLOCK: - p->p_sigmask &= ~mask; - break; - case LINUX_SIG_SETMASK: - p->p_sigmask = (mask & ~sigcantmask); - break; - default: - error = EINVAL; - break; + int error, s; + sigset_t mask; + + error = 0; + p->p_retval[0] = 0; + + if (old != NULL) + bsd_to_linux_sigset(&p->p_sigmask, old); + + if (new != NULL) { + linux_to_bsd_sigset(new, &mask); + + s = splhigh(); + + switch (how) { + case LINUX_SIG_BLOCK: + SIGSETOR(p->p_sigmask, mask); + SIG_CANTMASK(p->p_sigmask); + break; + case LINUX_SIG_UNBLOCK: + SIGSETNAND(p->p_sigmask, mask); + break; + case LINUX_SIG_SETMASK: + p->p_sigmask = mask; + SIG_CANTMASK(p->p_sigmask); + break; + default: + error = EINVAL; + break; + } + + splx(s); } - splx(s); - } - - return error; + return (error); } int linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) { - linux_sigset_t mask; - linux_sigset_t omask; - int error; + linux_osigset_t mask; + linux_sigset_t set, oset; + int error; #ifdef DEBUG - printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how); + printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how); #endif - if (args->mask != NULL) { - error = copyin(args->mask, &mask, sizeof(linux_sigset_t)); - if (error) - return error; - } + if (args->mask != NULL) { + error = copyin(args->mask, &mask, sizeof(linux_osigset_t)); + if (error) + return (error); + LINUX_SIGEMPTYSET(set); + set.__bits[0] = mask; + } - error = linux_do_sigprocmask(p, args->how, - args->mask ? &mask : NULL, - args->omask ? &omask : NULL); + error = linux_do_sigprocmask(p, args->how, + args->mask ? &set : NULL, + args->omask ? &oset : NULL); - if (!error && args->omask != NULL) { - error = copyout(&omask, args->omask, sizeof(linux_sigset_t)); - } + if (args->omask != NULL && !error) { + mask = oset.__bits[0]; + error = copyout(&mask, args->omask, sizeof(linux_osigset_t)); + } - return error; + return (error); } int linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) { - linux_new_sigset_t new_mask; - linux_sigset_t old_mask; - int error; + linux_sigset_t set, oset; + int error; #ifdef DEBUG - printf("Linux-emul(%ld): rt_sigprocmask(%d, %p, %p, %d)\n", - (long)p->p_pid, args->how, (void *)args->mask, - (void *)args->omask, args->sigsetsize); + printf("Linux-emul(%ld): rt_sigprocmask(%d, %p, %p, %d)\n", + (long)p->p_pid, args->how, (void *)args->mask, + (void *)args->omask, args->sigsetsize); #endif - if (args->sigsetsize != sizeof(linux_new_sigset_t)) - return EINVAL; - - if (args->mask != NULL) { - error = copyin(args->mask, &new_mask, sizeof(linux_new_sigset_t)); - if (error) - return error; + if (args->sigsetsize != sizeof(linux_sigset_t)) + return EINVAL; -#ifdef DEBUG - if (new_mask.sig[1] != 0) - printf("LINUX(%ld): rt_sigprocmask: sig[1] = 0x%08lx\n", - (long)p->p_pid, new_mask.sig[1]); -#endif - } + if (args->mask != NULL) { + error = copyin(args->mask, &set, sizeof(linux_sigset_t)); + if (error) + return (error); + } - error = linux_do_sigprocmask(p, args->how, - args->mask ? new_mask.sig : NULL, - args->omask ? &old_mask : NULL); + error = linux_do_sigprocmask(p, args->how, + args->mask ? &set : NULL, + args->omask ? &oset : NULL); - if (!error && args->omask != NULL) { - new_mask.sig[0] = old_mask; - error = copyout(&new_mask, args->omask, sizeof(linux_new_sigset_t)); - } + if (args->omask != NULL && !error) { + error = copyout(&oset, args->omask, sizeof(linux_sigset_t)); + } - return error; + return (error); } int linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) { + linux_sigset_t mask; + #ifdef DEBUG - printf("Linux-emul(%d): siggetmask()\n", p->p_pid); + printf("Linux-emul(%d): siggetmask()\n", p->p_pid); #endif - p->p_retval[0] = bsd_to_linux_sigset(p->p_sigmask); - return 0; + + bsd_to_linux_sigset(&p->p_sigmask, &mask); + p->p_retval[0] = mask.__bits[0]; + return (0); } int linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args) { - int s; - sigset_t mask; + linux_sigset_t lset; + sigset_t bset; + int s; #ifdef DEBUG - printf("Linux-emul(%ld): sigsetmask(%08lx)\n", - (long)p->p_pid, (unsigned long)args->mask); + printf("Linux-emul(%ld): sigsetmask(%08lx)\n", + (long)p->p_pid, (unsigned long)args->mask); #endif - p->p_retval[0] = bsd_to_linux_sigset(p->p_sigmask); - mask = linux_to_bsd_sigset(args->mask); - s = splhigh(); - p->p_sigmask = mask & ~sigcantmask; - splx(s); - return 0; + bsd_to_linux_sigset(&p->p_sigmask, &lset); + p->p_retval[0] = lset.__bits[0]; + LINUX_SIGEMPTYSET(lset); + lset.__bits[0] = args->mask; + linux_to_bsd_sigset(&lset, &bset); + s = splhigh(); + p->p_sigmask = bset; + SIG_CANTMASK(p->p_sigmask); + splx(s); + return (0); } int linux_sigpending(struct proc *p, struct linux_sigpending_args *args) { - linux_sigset_t linux_sig; + sigset_t bset; + linux_sigset_t lset; + linux_osigset_t mask; #ifdef DEBUG - printf("Linux-emul(%d): sigpending(*)\n", p->p_pid); + printf("Linux-emul(%d): sigpending(*)\n", p->p_pid); #endif - linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask); - return copyout(&linux_sig, args->mask, sizeof(linux_sig)); + + bset = p->p_siglist; + SIGSETAND(bset, p->p_sigmask); + bsd_to_linux_sigset(&bset, &lset); + mask = lset.__bits[0]; + return (copyout(&mask, args->mask, sizeof(mask))); } /* @@ -424,43 +426,94 @@ linux_sigpending(struct proc *p, struct linux_sigpending_args *args) int linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args) { - struct sigsuspend_args tmp; + struct sigsuspend_args bsd; + sigset_t *sigmask; + linux_sigset_t mask; + caddr_t sg = stackgap_init(); #ifdef DEBUG - printf("Linux-emul(%ld): sigsuspend(%08lx)\n", - (long)p->p_pid, (unsigned long)args->mask); + printf("Linux-emul(%ld): sigsuspend(%08lx)\n", + (long)p->p_pid, (unsigned long)args->mask); #endif - tmp.mask = linux_to_bsd_sigset(args->mask); - return sigsuspend(p, &tmp); + + sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); + LINUX_SIGEMPTYSET(mask); + mask.__bits[0] = args->mask; + linux_to_bsd_sigset(&mask, sigmask); + bsd.sigmask = sigmask; + return (sigsuspend(p, &bsd)); +} + +int +linux_rt_sigsuspend(p, uap) + struct proc *p; + struct linux_rt_sigsuspend_args *uap; +{ + linux_sigset_t lmask; + sigset_t *bmask; + struct sigsuspend_args bsd; + caddr_t sg = stackgap_init(); + int error; + +#ifdef DEBUG + printf("Linux-emul(%ld): rt_sigsuspend(%p, %d)\n", (long)p->p_pid, + (void *)uap->newset, uap->sigsetsize); +#endif + + if (uap->sigsetsize != sizeof(linux_sigset_t)) + return (EINVAL); + + error = copyin(uap->newset, &lmask, sizeof(linux_sigset_t)); + if (error) + return (error); + + bmask = stackgap_alloc(&sg, sizeof(sigset_t)); + linux_to_bsd_sigset(&lmask, bmask); + bsd.sigmask = bmask; + return (sigsuspend(p, &bsd)); } int linux_pause(struct proc *p, struct linux_pause_args *args) { - struct sigsuspend_args tmp; + struct sigsuspend_args bsd; + sigset_t *sigmask; + caddr_t sg = stackgap_init(); #ifdef DEBUG - printf("Linux-emul(%d): pause()\n", p->p_pid); + printf("Linux-emul(%d): pause()\n", p->p_pid); #endif - tmp.mask = p->p_sigmask; - return sigsuspend(p, &tmp); + + sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); + *sigmask = p->p_sigmask; + bsd.sigmask = sigmask; + return sigsuspend(p, &bsd); } int linux_kill(struct proc *p, struct linux_kill_args *args) { - struct kill_args /* { - int pid; - int signum; - } */ tmp; + struct kill_args /* { + int pid; + int signum; + } */ tmp; #ifdef DEBUG - printf("Linux-emul(%d): kill(%d, %d)\n", - p->p_pid, args->pid, args->signum); + printf("Linux-emul(%d): kill(%d, %d)\n", + p->p_pid, args->pid, args->signum); #endif - if (args->signum < 0 || args->signum >= LINUX_NSIG) - return EINVAL; - tmp.pid = args->pid; - tmp.signum = linux_to_bsd_signal[args->signum]; - return kill(p, &tmp); + + /* + * Allow signal 0 as a means to check for privileges + */ + if (args->signum < 0 || args->signum > LINUX_NSIG) + return EINVAL; + + if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) + tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; + else + tmp.signum = args->signum; + + tmp.pid = args->pid; + return (kill(p, &tmp)); } |