diff options
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 20 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.c | 615 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_misc.c | 9 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_signal.c | 121 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_signal.h | 13 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_sysvec.c | 5 |
6 files changed, 428 insertions, 355 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 919a5e7..ff5ba44 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -47,6 +47,7 @@ #include <sys/vnode.h> #include <sys/wait.h> #include <sys/time.h> +#include <sys/signalvar.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -67,6 +68,9 @@ #include <posix4/sched.h> +#define BSD_TO_LINUX_SIGNAL(sig) \ + (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) + static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, @@ -622,7 +626,9 @@ linux_clone(struct proc *p, struct linux_clone_args *args) exit_signal = args->flags & 0x000000ff; if (exit_signal >= LINUX_NSIG) return EINVAL; - exit_signal = linux_to_bsd_signal[exit_signal]; + + if (exit_signal <= LINUX_SIGTBLSZ) + exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; /* RFTHREAD probably not necessary here, but it shouldn't hurt either */ ff |= RFTHREAD; @@ -979,10 +985,10 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args) return error; if (WIFSIGNALED(tmpstat)) tmpstat = (tmpstat & 0xffffff80) | - bsd_to_linux_signal[WTERMSIG(tmpstat)]; + BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); else if (WIFSTOPPED(tmpstat)) tmpstat = (tmpstat & 0xffff00ff) | - (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); return copyout(&tmpstat, args->status, sizeof(int)); } else return 0; @@ -1015,17 +1021,17 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args) if ((error = wait4(p, &tmp)) != 0) return error; - p->p_siglist &= ~sigmask(SIGCHLD); + SIGDELSET(p->p_siglist, SIGCHLD); if (args->status) { if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0) return error; if (WIFSIGNALED(tmpstat)) tmpstat = (tmpstat & 0xffffff80) | - bsd_to_linux_signal[WTERMSIG(tmpstat)]; + BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); else if (WIFSTOPPED(tmpstat)) tmpstat = (tmpstat & 0xffff00ff) | - (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); return copyout(&tmpstat, args->status, sizeof(int)); } else return 0; @@ -1312,7 +1318,7 @@ linux_sched_setscheduler(p, uap) #ifdef DEBUG printf("Linux-emul(%ld): sched_setscheduler(%d, %d, %p)\n", - (long)p->p_pid, uap->pid, uap->policy, (void *)uap->param); + (long)p->p_pid, uap->pid, uap->policy, (const void *)uap->param); #endif switch (uap->policy) { diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index 9f2200e..39334a7 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/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)); } diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 9535cba..9720abc 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -100,7 +100,6 @@ #define BSD_DIRENT(cp) ((struct dirent *)(cp)) -extern int bsd_to_svr4_sig[]; static int svr4_mknod __P((struct proc *, register_t *, char *, svr4_mode_t, svr4_dev_t)); @@ -159,11 +158,11 @@ svr4_sys_wait(p, uap) if (WIFSIGNALED(st)) { sig = WTERMSIG(st); if (sig >= 0 && sig < NSIG) - st = (st & ~0177) | bsd_to_svr4_sig[sig]; + st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig); } else if (WIFSTOPPED(st)) { sig = WSTOPSIG(st); if (sig >= 0 && sig < NSIG) - st = (st & ~0xff00) | (bsd_to_svr4_sig[sig] << 8); + st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8); } /* @@ -1119,7 +1118,7 @@ svr4_setinfo(p, st, s) } else if (WIFSTOPPED(st)) { sig = WSTOPSIG(st); if (sig >= 0 && sig < NSIG) - i.si_status = bsd_to_svr4_sig[sig]; + i.si_status = SVR4_BSD2SVR4_SIG(sig); if (i.si_status == SVR4_SIGCONT) i.si_code = SVR4_CLD_CONTINUED; @@ -1128,7 +1127,7 @@ svr4_setinfo(p, st, s) } else { sig = WTERMSIG(st); if (sig >= 0 && sig < NSIG) - i.si_status = bsd_to_svr4_sig[sig]; + i.si_status = SVR4_BSD2SVR4_SIG(sig); if (WCOREDUMP(st)) i.si_code = SVR4_CLD_DUMPED; diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c index b123987..5b8838c 100644 --- a/sys/compat/svr4/svr4_signal.c +++ b/sys/compat/svr4/svr4_signal.c @@ -47,24 +47,19 @@ #include <svr4/svr4_util.h> #include <svr4/svr4_ucontext.h> -#define sigemptyset(s) memset((s), 0, sizeof(*(s))) -#define sigismember(s, n) (*(s) & sigmask(n)) -#define sigaddset(s, n) (*(s) |= sigmask(n)) - #define svr4_sigmask(n) (1 << (((n) - 1) & 31)) #define svr4_sigword(n) (((n) - 1) >> 5) #define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s))) +#define svr4_sigfillset(s) memset((s), 0xffffffff, sizeof(*(s))) #define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n)) #define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n)) -static __inline void svr4_sigfillset __P((svr4_sigset_t *)); void svr4_to_bsd_sigaction __P((const struct svr4_sigaction *, struct sigaction *)); void bsd_to_svr4_sigaction __P((const struct sigaction *, struct svr4_sigaction *)); -int bsd_to_svr4_sig[] = { - 0, +int bsd_to_svr4_sig[SVR4_SIGTBLSZ] = { SVR4_SIGHUP, SVR4_SIGINT, SVR4_SIGQUIT, @@ -98,8 +93,7 @@ int bsd_to_svr4_sig[] = { SVR4_SIGUSR2, }; -int svr4_to_bsd_sig[] = { - 0, +int svr4_to_bsd_sig[SVR4_SIGTBLSZ] = { SIGHUP, SIGINT, SIGQUIT, @@ -133,17 +127,6 @@ int svr4_to_bsd_sig[] = { SIGXFSZ, }; -static __inline void -svr4_sigfillset(s) - svr4_sigset_t *s; -{ - int i; - - svr4_sigemptyset(s); - for (i = 1; i < SVR4_NSIG; i++) - svr4_sigaddset(s, i); -} - void svr4_to_bsd_sigset(sss, bss) const svr4_sigset_t *sss; @@ -151,17 +134,20 @@ svr4_to_bsd_sigset(sss, bss) { int i, newsig; - sigemptyset(bss); - for (i = 1; i < SVR4_NSIG; i++) { + SIGEMPTYSET(*bss); + bss->__bits[0] = sss->bits[0] & ~((1U << SVR4_SIGTBLSZ) - 1); + bss->__bits[1] = sss->bits[1]; + bss->__bits[2] = sss->bits[2]; + bss->__bits[3] = sss->bits[3]; + for (i = 1; i <= SVR4_SIGTBLSZ; i++) { if (svr4_sigismember(sss, i)) { - newsig = svr4_to_bsd_sig[i]; + newsig = svr4_to_bsd_sig[_SIG_IDX(i)]; if (newsig) - sigaddset(bss, newsig); + SIGADDSET(*bss, newsig); } } } - void bsd_to_svr4_sigset(bss, sss) const sigset_t *bss; @@ -170,16 +156,19 @@ bsd_to_svr4_sigset(bss, sss) int i, newsig; svr4_sigemptyset(sss); - for (i = 1; i < NSIG; i++) { - if (sigismember(bss, i)) { - newsig = bsd_to_svr4_sig[i]; + sss->bits[0] = bss->__bits[0] & ~((1U << SVR4_SIGTBLSZ) - 1); + sss->bits[1] = bss->__bits[1]; + sss->bits[2] = bss->__bits[2]; + sss->bits[3] = bss->__bits[3]; + for (i = 1; i <= SVR4_SIGTBLSZ; i++) { + if (SIGISMEMBER(*bss, i)) { + newsig = bsd_to_svr4_sig[_SIG_IDX(i)]; if (newsig) svr4_sigaddset(sss, newsig); } } } - /* * XXX: Only a subset of the flags is currently implemented. */ @@ -293,9 +282,9 @@ svr4_sys_sigaction(p, uap) } else nbsa = NULL; - SCARG(&sa, signum) = svr4_to_bsd_sig[SCARG(uap, signum)]; - SCARG(&sa, nsa) = nbsa; - SCARG(&sa, osa) = obsa; + SCARG(&sa, sig) = SVR4_SVR42BSD_SIG(SCARG(uap, signum)); + SCARG(&sa, act) = nbsa; + SCARG(&sa, oact) = obsa; if ((error = sigaction(p, &sa)) != 0) return error; @@ -342,7 +331,7 @@ svr4_sys_sigaltstack(p, uap) } else nbss = NULL; - SCARG(&sa, nss) = nbss; + SCARG(&sa, ss) = nbss; SCARG(&sa, oss) = obss; if ((error = sigaltstack(p, &sa)) != 0) @@ -367,12 +356,13 @@ svr4_sys_signal(p, uap) register struct proc *p; struct svr4_sys_signal_args *uap; { - int signum = svr4_to_bsd_sig[SVR4_SIGNO(SCARG(uap, signum))]; + int signum; int error, *retval; caddr_t sg = stackgap_init(); + signum = SVR4_SVR42BSD_SIG(SVR4_SIGNO(SCARG(uap, signum))); retval = p->p_retval; - if (signum <= 0 || signum >= SVR4_NSIG) + if (signum <= 0 || signum > SVR4_NSIG) return (EINVAL); switch (SVR4_SIGCALL(SCARG(uap, signum))) { @@ -388,12 +378,12 @@ svr4_sys_signal(p, uap) nbsa = stackgap_alloc(&sg, sizeof(struct sigaction)); obsa = stackgap_alloc(&sg, sizeof(struct sigaction)); - SCARG(&sa_args, signum) = signum; - SCARG(&sa_args, nsa) = nbsa; - SCARG(&sa_args, osa) = obsa; + SCARG(&sa_args, sig) = signum; + SCARG(&sa_args, act) = nbsa; + SCARG(&sa_args, oact) = obsa; sa.sa_handler = (sig_t) SCARG(uap, handler); - sigemptyset(&sa.sa_mask); + SIGEMPTYSET(sa.sa_mask); sa.sa_flags = 0; if (signum != SIGALRM) @@ -417,18 +407,28 @@ svr4_sys_signal(p, uap) sighold: { struct sigprocmask_args sa; + sigset_t *set; + set = stackgap_alloc(&sg, sizeof(sigset_t)); + SIGEMPTYSET(*set); + SIGADDSET(*set, signum); SCARG(&sa, how) = SIG_BLOCK; - SCARG(&sa, mask) = sigmask(signum); + SCARG(&sa, set) = set; + SCARG(&sa, oset) = NULL; return sigprocmask(p, &sa); } case SVR4_SIGRELSE_MASK: { struct sigprocmask_args sa; + sigset_t *set; + set = stackgap_alloc(&sg, sizeof(sigset_t)); + SIGEMPTYSET(*set); + SIGADDSET(*set, signum); SCARG(&sa, how) = SIG_UNBLOCK; - SCARG(&sa, mask) = sigmask(signum); + SCARG(&sa, set) = set; + SCARG(&sa, oset) = NULL; return sigprocmask(p, &sa); } @@ -438,12 +438,12 @@ sighold: struct sigaction *bsa, sa; bsa = stackgap_alloc(&sg, sizeof(struct sigaction)); - SCARG(&sa_args, signum) = signum; - SCARG(&sa_args, nsa) = bsa; - SCARG(&sa_args, osa) = NULL; + SCARG(&sa_args, sig) = signum; + SCARG(&sa_args, act) = bsa; + SCARG(&sa_args, oact) = NULL; sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); + SIGEMPTYSET(sa.sa_mask); sa.sa_flags = 0; if ((error = copyout(&sa, bsa, sizeof(sa))) != 0) return error; @@ -457,8 +457,12 @@ sighold: case SVR4_SIGPAUSE_MASK: { struct sigsuspend_args sa; + sigset_t *set; - SCARG(&sa, mask) = p->p_sigmask & ~sigmask(signum); + set = stackgap_alloc(&sg, sizeof(sigset_t)); + *set = p->p_sigmask; + SIGDELSET(*set, signum); + SCARG(&sa, sigmask) = set; return sigsuspend(p, &sa); } @@ -498,15 +502,17 @@ svr4_sys_sigprocmask(p, uap) switch (SCARG(uap, how)) { case SVR4_SIG_BLOCK: - p->p_sigmask |= bss & ~sigcantmask; + SIGSETOR(p->p_sigmask, bss); + SIG_CANTMASK(p->p_sigmask); break; case SVR4_SIG_UNBLOCK: - p->p_sigmask &= ~bss; + SIGSETNAND(p->p_sigmask, bss); break; case SVR4_SIG_SETMASK: - p->p_sigmask = bss & ~sigcantmask; + p->p_sigmask = bss; + SIG_CANTMASK(p->p_sigmask); break; default: @@ -533,7 +539,8 @@ svr4_sys_sigpending(p, uap) case 1: /* sigpending */ if (SCARG(uap, mask) == NULL) return 0; - bss = p->p_siglist & p->p_sigmask; + bss = p->p_siglist; + SIGSETAND(bss, p->p_sigmask); bsd_to_svr4_sigset(&bss, &sss); break; @@ -554,16 +561,18 @@ svr4_sys_sigsuspend(p, uap) struct svr4_sys_sigsuspend_args *uap; { svr4_sigset_t sss; - sigset_t bss; + sigset_t *bss; struct sigsuspend_args sa; int error; + caddr_t sg = stackgap_init(); if ((error = copyin(SCARG(uap, ss), &sss, sizeof(sss))) != 0) return error; - svr4_to_bsd_sigset(&sss, &bss); + bss = stackgap_alloc(&sg, sizeof(sigset_t)); + svr4_to_bsd_sigset(&sss, bss); - SCARG(&sa, mask) = bss; + SCARG(&sa, sigmask) = bss; return sigsuspend(p, &sa); } @@ -576,7 +585,7 @@ svr4_sys_kill(p, uap) struct kill_args ka; SCARG(&ka, pid) = SCARG(uap, pid); - SCARG(&ka, signum) = svr4_to_bsd_sig[SCARG(uap, signum)]; + SCARG(&ka, signum) = SVR4_SVR42BSD_SIG(SCARG(uap, signum)); return kill(p, &ka); } @@ -592,7 +601,7 @@ svr4_sys_context(p, uap) switch (uap->func) { case 0: DPRINTF(("getcontext(%p)\n", uap->uc)); - svr4_getcontext(p, &uc, p->p_sigmask, + svr4_getcontext(p, &uc, &p->p_sigmask, p->p_sigacts->ps_sigstk.ss_flags & SS_ONSTACK); return copyout(&uc, uap->uc, sizeof(uc)); @@ -620,6 +629,6 @@ svr4_sys_pause(p, uap) { struct sigsuspend_args bsa; - SCARG(&bsa, mask) = p->p_sigmask; + SCARG(&bsa, sigmask) = &p->p_sigmask; return sigsuspend(p, &bsa); } diff --git a/sys/compat/svr4/svr4_signal.h b/sys/compat/svr4/svr4_signal.h index 8fb861d..b7bb132 100644 --- a/sys/compat/svr4/svr4_signal.h +++ b/sys/compat/svr4/svr4_signal.h @@ -68,7 +68,8 @@ #define SVR4_SIGPROF 29 #define SVR4_SIGXCPU 30 #define SVR4_SIGXFSZ 31 -#define SVR4_NSIG 32 +#define SVR4_NSIG 128 +#define SVR4_SIGTBLSZ 31 #define SVR4_SIGNO_MASK 0x00FF #define SVR4_SIGNAL_MASK 0x0000 @@ -91,6 +92,14 @@ typedef void (*svr4_sig_t) __P((int, svr4_siginfo_t *, void *)); #define SVR4_SIG_UNBLOCK 2 #define SVR4_SIG_SETMASK 3 +extern int bsd_to_svr4_sig[]; +extern int svr4_to_bsd_sig[]; + +#define SVR4_BSD2SVR4_SIG(sig) \ + (((sig) <= SVR4_SIGTBLSZ) ? bsd_to_svr4_sig[_SIG_IDX(sig)] : sig) +#define SVR4_SVR42BSD_SIG(sig) \ + (((sig) <= SVR4_SIGTBLSZ) ? svr4_to_bsd_sig[_SIG_IDX(sig)] : sig) + typedef struct { u_long bits[4]; } svr4_sigset_t; @@ -127,6 +136,6 @@ void bsd_to_svr4_sigaltstack __P((const struct sigaltstack *, struct svr4_sigalt void bsd_to_svr4_sigset __P((const sigset_t *, svr4_sigset_t *)); void svr4_to_bsd_sigaltstack __P((const struct svr4_sigaltstack *, struct sigaltstack *)); void svr4_to_bsd_sigset __P((const svr4_sigset_t *, sigset_t *)); -void svr4_sendsig(sig_t, int, int, u_long); +void svr4_sendsig(sig_t, int, sigset_t *, u_long); #endif /* !_SVR4_SIGNAL_H_ */ diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 099bb9c..6a2bc03 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -72,9 +72,6 @@ #include <svr4/svr4_siginfo.h> #include <svr4/svr4_util.h> -extern int bsd_to_svr4_sig[]; -extern int svr4_to_bsd_sig[]; - int bsd_to_svr4_errno[ELAST+1] = { 0, SVR4_EPERM, @@ -176,7 +173,7 @@ struct sysentvec svr4_sysvec = { SVR4_SYS_MAXSYSCALL, svr4_sysent, 0xff, - NSIG, + SVR4_SIGTBLSZ, bsd_to_svr4_sig, ELAST, /* ELAST */ bsd_to_svr4_errno, |