diff -ru3 ../../../sys/alpha/alpha/locore.s sys/alpha/alpha/locore.s --- ../../../sys/alpha/alpha/locore.s Tue Feb 19 16:21:31 2002 +++ sys/alpha/alpha/locore.s Mon Oct 21 13:32:12 2002 @@ -53,6 +53,8 @@ * rights to redistribute these changes. */ +#include "opt_compat.h" + #include #include #include @@ -190,15 +192,55 @@ jsr ra, (t12) /* call the signal handler (t12==pv) */ ldq a0, 0(sp) /* get the sigcontext pointer */ lda sp, 16(sp) - CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */ + ldiq v0, SYS_sigreturn + call_pal PAL_OSF1_callsys /* and call sigreturn() with it. */ mov v0, a0 /* if that failed, get error code */ - CALLSYS_NOERROR(exit) /* and call exit() with it. */ -XNESTED(esigcode,0) + ldiq v0, SYS_exit + call_pal PAL_OSF1_callsys /* and call exit() with it. */ END(sigcode) +#ifdef COMPAT_43 +NESTED(osigcode,0,0,ra,0,0) + lda sp, -16(sp) /* save the sigcontext pointer */ + stq a2, 0(sp) + jsr ra, (t12) /* call the signal handler (t12==pv) */ + ldq a0, 0(sp) /* get the sigcontext pointer */ + lda sp, 16(sp) + ldiq v0, 103 /* Old 3.x SYS_sigreturn */ + call_pal PAL_OSF1_callsys /* and call sigreturn() with it. */ + mov v0, a0 /* if that failed, get error code */ + ldiq v0, SYS_exit + call_pal PAL_OSF1_callsys /* and call exit() with it. */ + END(osigcode) +#endif + +#ifdef COMPAT_FREEBSD4 +NESTED(freebsd4_sigcode,0,0,ra,0,0) + lda sp, -16(sp) /* save the sigcontext pointer */ + stq a2, 0(sp) + jsr ra, (t12) /* call the signal handler (t12==pv) */ + ldq a0, 0(sp) /* get the sigcontext pointer */ + lda sp, 16(sp) + ldiq v0, 344 /* Old 4.x SYS_sigreturn */ + call_pal PAL_OSF1_callsys /* and call sigreturn() with it. */ + mov v0, a0 /* if that failed, get error code */ + ldiq v0, SYS_exit + call_pal PAL_OSF1_callsys /* and call exit() with it. */ + END(freebsd4_sigcode) +#endif +EXPORT(esigcode) /* end of all sigcode */ + .data - EXPORT(szsigcode) - .quad esigcode-sigcode +EXPORT(szsigcode) + .long esigcode-sigcode +#ifdef COMPAT_43 +EXPORT(szosigcode) + .long esigcode-osigcode +#endif +#ifdef COMPAT_FREEBSD4 +EXPORT(szfreebsd4_sigcode) + .long esigcode-freebsd4_sigcode +#endif .text /**************************************************************************/ diff -ru3 ../../../sys/alpha/alpha/machdep.c sys/alpha/alpha/machdep.c --- ../../../sys/alpha/alpha/machdep.c Fri Sep 20 17:31:44 2002 +++ sys/alpha/alpha/machdep.c Mon Oct 21 17:42:52 2002 @@ -232,6 +232,10 @@ #ifdef COMPAT_43 void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); #endif +#ifdef COMPAT_FREEBSD4 +static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, + u_long code); +#endif static void identifycpu(void); @@ -1250,7 +1254,7 @@ /* * Set up the registers to return to sigcode. */ - frame->tf_regs[FRAME_PC] = PS_STRINGS - (esigcode - sigcode); + frame->tf_regs[FRAME_PC] = PS_STRINGS - szosigcode; frame->tf_regs[FRAME_A0] = sig; frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */ PROC_LOCK(p); @@ -1264,6 +1268,121 @@ } #endif +#ifdef COMPAT_FREEBSD4 +static void +freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +{ + struct proc *p; + struct thread *td; + struct trapframe *frame; + struct sigacts *psp; + struct sigframe4 sf, *sfp; + int oonstack, rndfsize; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + psp = p->p_sigacts; + + frame = td->td_frame; + oonstack = sigonstack(alpha_pal_rdusp()); + rndfsize = ((sizeof(sf) + 15) / 16) * 16; + + /* save user context */ + bzero(&sf, sizeof(sf)); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_stack = p->p_sigstk; + sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) + ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; + sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; + + fill_regs(td, (struct reg *)sf.sf_uc.uc_mcontext.mc_regs); + sf.sf_uc.uc_mcontext.mc_regs[R_SP] = alpha_pal_rdusp(); + sf.sf_uc.uc_mcontext.mc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ + sf.sf_uc.uc_mcontext.mc_regs[R_PS] = frame->tf_regs[FRAME_PS]; + sf.sf_uc.uc_mcontext.mc_regs[R_PC] = frame->tf_regs[FRAME_PC]; + sf.sf_uc.uc_mcontext.mc_regs[R_TRAPARG_A0] = + frame->tf_regs[FRAME_TRAPARG_A0]; + sf.sf_uc.uc_mcontext.mc_regs[R_TRAPARG_A1] = + frame->tf_regs[FRAME_TRAPARG_A1]; + sf.sf_uc.uc_mcontext.mc_regs[R_TRAPARG_A2] = + frame->tf_regs[FRAME_TRAPARG_A2]; + + /* + * Allocate and validate space for the signal handler + * context. Note that if the stack is in P0 space, the + * call to grow() is a nop, and the useracc() check + * will fail if the process has not already allocated + * the space with a `brk'. + */ + if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sfp = (struct sigframe4 *)((caddr_t)p->p_sigstk.ss_sp + + p->p_sigstk.ss_size - rndfsize); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + p->p_sigstk.ss_flags |= SS_ONSTACK; +#endif + } else + sfp = (struct sigframe4 *)(alpha_pal_rdusp() - rndfsize); + PROC_UNLOCK(p); + + /* save the floating-point state, if necessary, then copy it. */ + alpha_fpstate_save(td, 1); + sf.sf_uc.uc_mcontext.mc_ownedfp = td->td_md.md_flags & MDTD_FPUSED; + bcopy(&td->td_pcb->pcb_fp, + (struct fpreg *)sf.sf_uc.uc_mcontext.mc_fpregs, + sizeof(struct fpreg)); + sf.sf_uc.uc_mcontext.mc_fp_control = td->td_pcb->pcb_fp_control; + +#ifdef COMPAT_OSF1 + /* + * XXX Create an OSF/1-style sigcontext and associated goo. + */ +#endif + + /* + * copy the frame out to userland. + */ + if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + PROC_LOCK(p); + SIGACTION(p, SIGILL) = SIG_DFL; + SIGDELSET(p->p_sigignore, SIGILL); + SIGDELSET(p->p_sigcatch, SIGILL); + SIGDELSET(p->p_sigmask, SIGILL); + psignal(p, SIGILL); + return; + } + + /* + * Set up the registers to return to sigcode. + */ + frame->tf_regs[FRAME_PC] = PS_STRINGS - szfreebsd4_sigcode; + frame->tf_regs[FRAME_A0] = sig; + PROC_LOCK(p); + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si); + + /* Fill in POSIX parts */ + sf.sf_si.si_signo = sig; + sf.sf_si.si_code = code; + sf.sf_si.si_addr = (void*)frame->tf_regs[FRAME_TRAPARG_A0]; + sf.sf_si.si_pid = p->p_pid; + sf.sf_si.si_uid = p->p_ucred->cr_uid; + } + else + frame->tf_regs[FRAME_A1] = code; + + frame->tf_regs[FRAME_A2] = (u_int64_t)&(sfp->sf_uc); + frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */ + frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */ + alpha_pal_wrusp((unsigned long)sfp); +} +#endif /* COMPAT_FREEBSD4 */ + void sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { @@ -1278,6 +1397,12 @@ p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; +#ifdef COMPAT_FREEBSD4 + if (SIGISMEMBER(psp->ps_freebsd4, sig)) { + freebsd4_sendsig(catcher, sig, mask, code); + return; + } +#endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { osendsig(catcher, sig, mask, code); @@ -1377,7 +1502,7 @@ /* * Set up the registers to return to sigcode. */ - frame->tf_regs[FRAME_PC] = PS_STRINGS - (esigcode - sigcode); + frame->tf_regs[FRAME_PC] = PS_STRINGS - szsigcode; frame->tf_regs[FRAME_A0] = sig; PROC_LOCK(p); if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { @@ -1419,13 +1544,13 @@ * * MPSAFE */ +#ifdef COMPAT_43 int osigreturn(struct thread *td, struct osigreturn_args /* { struct osigcontext *sigcntxp; } */ *uap) { -#ifdef COMPAT_43 struct osigcontext *scp, ksc; struct proc *p = td->td_proc; @@ -1479,10 +1604,82 @@ sizeof(struct fpreg)); td->td_pcb->pcb_fp_control = ksc.sc_fp_control; return (EJUSTRETURN); -#else /* !COMPAT_43 */ - return (ENOSYS); +} #endif /* COMPAT_43 */ + +#ifdef COMPAT_FREEBSD4 +/* + * MPSAFE + */ +int +freebsd4_sigreturn(struct thread *td, + struct freebsd4_sigreturn_args /* { + const struct ucontext4 *sigcntxp; + } */ *uap) +{ + struct ucontext4 uc; + const struct ucontext4 *ucp; + struct pcb *pcb; + unsigned long val; + struct proc *p; + int error; + + ucp = uap->sigcntxp; + pcb = td->td_pcb; + p = td->td_proc; + + /* + * Fetch the entire context structure at once for speed. + * Note that struct osigcontext is smaller than a ucontext_t, + * so even if copyin() faults, we may have actually gotten a complete + * struct osigcontext. + */ + error = copyin(ucp, &uc, sizeof(ucontext_t)); + if (error != 0) { +#ifdef COMPAT_43 + if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) + return osigreturn(td, (struct osigreturn_args *)uap); +#endif + return (error); + } + +#ifdef COMPAT_43 + if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) + return osigreturn(td, (struct osigreturn_args *)uap); +#endif + + /* + * Restore the user-supplied information + */ + set_regs(td, (struct reg *)uc.uc_mcontext.mc_regs); + val = (uc.uc_mcontext.mc_regs[R_PS] | ALPHA_PSL_USERSET) & + ~ALPHA_PSL_USERCLR; + td->td_frame->tf_regs[FRAME_PS] = val; + td->td_frame->tf_regs[FRAME_PC] = uc.uc_mcontext.mc_regs[R_PC]; + td->td_frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */ + alpha_pal_wrusp(uc.uc_mcontext.mc_regs[R_SP]); + + PROC_LOCK(p); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + if (uc.uc_mcontext.mc_onstack & 1) + p->p_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigstk.ss_flags &= ~SS_ONSTACK; +#endif + + p->p_sigmask = uc.uc_sigmask; + SIG_CANTMASK(p->p_sigmask); + signotify(p); + PROC_UNLOCK(p); + + /* XXX ksc.sc_ownedfp ? */ + alpha_fpstate_drop(td); + bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs, + &td->td_pcb->pcb_fp, sizeof(struct fpreg)); + td->td_pcb->pcb_fp_control = uc.uc_mcontext.mc_fp_control; + return (EJUSTRETURN); } +#endif /* COMPAT_FREEBSD4 */ /* * MPSAFE @@ -1498,6 +1695,7 @@ struct pcb *pcb; unsigned long val; struct proc *p; + int error; ucp = uap->sigcntxp; pcb = td->td_pcb; @@ -1507,21 +1705,22 @@ if (sigdebug & SDB_FOLLOW) printf("sigreturn: pid %d, scp %p\n", p->p_pid, ucp); #endif - /* * Fetch the entire context structure at once for speed. * Note that struct osigcontext is smaller than a ucontext_t, * so even if copyin() faults, we may have actually gotten a complete * struct osigcontext. + * XXX we'll *still* be getting osigcontext's here due to longjmp(3) + * brain damage. */ - if (copyin(ucp, &uc, sizeof(ucontext_t))) { + error = copyin(ucp, &uc, sizeof(ucontext_t)); + if (error != 0) { #ifdef COMPAT_43 if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) return osigreturn(td, (struct osigreturn_args *)uap); #endif - return (EFAULT); + return (error); } - #ifdef COMPAT_43 if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) return osigreturn(td, (struct osigreturn_args *)uap); diff -ru3 ../../../sys/alpha/include/md_var.h sys/alpha/include/md_var.h --- ../../../sys/alpha/include/md_var.h Thu Aug 29 21:21:40 2002 +++ sys/alpha/include/md_var.h Thu Oct 17 13:58:18 2002 @@ -36,6 +36,12 @@ extern char sigcode[]; extern char esigcode[]; extern int szsigcode; +#ifdef COMPAT_43 +extern int szosigcode; +#endif +#ifdef COMPAT_FREEBSD4 +extern int szfreebsd4_sigcode; +#endif extern long Maxmem; extern int busdma_swi_pending; diff -ru3 ../../../sys/alpha/include/sigframe.h sys/alpha/include/sigframe.h --- ../../../sys/alpha/include/sigframe.h Tue Feb 19 16:21:31 2002 +++ sys/alpha/include/sigframe.h Mon Oct 21 13:32:12 2002 @@ -31,10 +31,12 @@ #ifndef _MACHINE_SIGFRAME_H_ #define _MACHINE_SIGFRAME_H_ 1 -#ifdef _KERNEL -struct osigframe { - struct osigcontext sf_sc; - osiginfo_t sf_si; +#if defined(_KERNEL) && defined(COMPAT_FREEBSD4) +/* FreeBSD 4.x */ +struct sigframe4 { + unsigned long __spare__; + struct ucontext4 sf_uc; + siginfo_t sf_si; }; #endif diff -ru3 ../../../sys/alpha/include/signal.h sys/alpha/include/signal.h --- ../../../sys/alpha/include/signal.h Mon Oct 14 18:27:01 2002 +++ sys/alpha/include/signal.h Fri Oct 25 11:43:31 2002 @@ -47,7 +47,7 @@ /* * Only the kernel should need these old type definitions. */ -#ifdef _KERNEL +#if defined(_KERNEL) && defined(COMPAT_43) /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following @@ -58,8 +58,6 @@ * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline * representations of 'struct reg' and 'struct fpreg', respectively. */ -typedef unsigned int osigset_t; - struct osigcontext { long sc_onstack; /* sigstack state to restore */ long sc_mask; /* signal mask to restore */ diff -ru3 ../../../sys/alpha/include/ucontext.h sys/alpha/include/ucontext.h --- ../../../sys/alpha/include/ucontext.h Thu Jan 10 00:19:55 2002 +++ sys/alpha/include/ucontext.h Mon Oct 21 13:32:12 2002 @@ -50,4 +50,16 @@ long __spare__[6]; } mcontext_t; +#if defined(_KERNEL) && defined(COMPAT_FREEBSD4) +struct mcontext4 { + long mc_onstack; /* XXX - sigcontext compat. */ + unsigned long mc_regs[37]; + unsigned long mc_fpregs[32]; + unsigned long mc_fpcr; + unsigned long mc_fp_control; + long mc_ownedfp; + long __spare__[7]; +}; +#endif + #endif /* !_MACHINE_UCONTEXT_H_ */ diff -ru3 ../../../sys/alpha/osf1/osf1_signal.c sys/alpha/osf1/osf1_signal.c --- ../../../sys/alpha/osf1/osf1_signal.c Thu Oct 3 11:31:53 2002 +++ sys/alpha/osf1/osf1_signal.c Mon Oct 21 13:32:12 2002 @@ -33,6 +33,11 @@ * $FreeBSD: src/sys/alpha/osf1/osf1_signal.c,v 1.22 2002/10/01 17:15:46 jmallett Exp $ */ +#include "opt_compat.h" +#ifndef COMPAT_43 +#error "COMPAT_OSF1 requires COMPAT_43" +#endif + #include #include #include @@ -101,7 +106,6 @@ #define osf1_sigismember(s, n) (*(s) & sigmask(n)) #define osf1_sigaddset(s, n) (*(s) |= sigmask(n)) - void osf1_to_bsd_sigset(oss, bss) const osf1_sigset_t *oss; @@ -747,9 +751,6 @@ return (EJUSTRETURN); } -extern int -osigstack(struct thread *td, struct osf1_osigstack_args *uap); - int osf1_osigstack(td, uap) register struct thread *td; @@ -761,5 +762,5 @@ /* uprintf("osf1_osigstack: oss = %p, nss = %p",uap->oss, uap->nss); uprintf(" stack ptr = %p\n",p->p_sigacts->ps_sigstk.ss_sp);*/ - return(osigstack(td, uap)); + return(osigstack(td, (struct osigstack_args *)uap)); } diff -ru3 ../../../sys/conf/options sys/conf/options --- ../../../sys/conf/options Thu Oct 24 22:55:22 2002 +++ sys/conf/options Thu Oct 24 22:55:28 2002 @@ -77,6 +77,7 @@ COMPAT_43 opt_compat.h COMPAT_FREEBSD4 opt_compat.h COMPAT_SUNOS opt_compat.h +NO_COMPAT_FREEBSD4 opt_compat.h COMPILING_LINT opt_global.h CY_PCI_FASTINTR CONSPEED opt_comconsole.h Only in sys/i386/compile: DAINTREE Only in ../../../sys/i386/compile: GENERIC Only in sys/i386/conf: DAINTREE diff -ru3 ../../../sys/i386/i386/genassym.c sys/i386/i386/genassym.c --- ../../../sys/i386/i386/genassym.c Mon Sep 16 18:57:30 2002 +++ sys/i386/i386/genassym.c Mon Oct 21 13:32:13 2002 @@ -37,6 +37,7 @@ * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.129 2002/09/16 19:25:08 mini Exp $ */ +#include "opt_compat.h" #include "opt_kstack_pages.h" #include @@ -151,12 +152,20 @@ ASSYM(TF_CS, offsetof(struct trapframe, tf_cs)); ASSYM(TF_EFLAGS, offsetof(struct trapframe, tf_eflags)); ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler)); +#ifdef COMPAT_43 ASSYM(SIGF_SC, offsetof(struct osigframe, sf_siginfo.si_sc)); +#endif ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc)); +#ifdef COMPAT_43 ASSYM(SC_PS, offsetof(struct osigcontext, sc_ps)); ASSYM(SC_FS, offsetof(struct osigcontext, sc_fs)); ASSYM(SC_GS, offsetof(struct osigcontext, sc_gs)); ASSYM(SC_TRAPNO, offsetof(struct osigcontext, sc_trapno)); +#endif +#ifdef COMPAT_FREEBSD4 +ASSYM(UC4_EFLAGS, offsetof(struct ucontext4, uc_mcontext.mc_eflags)); +ASSYM(UC4_GS, offsetof(struct ucontext4, uc_mcontext.mc_gs)); +#endif ASSYM(UC_EFLAGS, offsetof(ucontext_t, uc_mcontext.mc_eflags)); ASSYM(UC_GS, offsetof(ucontext_t, uc_mcontext.mc_gs)); ASSYM(ENOENT, ENOENT); diff -ru3 ../../../sys/i386/i386/locore.s sys/i386/i386/locore.s --- ../../../sys/i386/i386/locore.s Mon Sep 16 18:57:30 2002 +++ sys/i386/i386/locore.s Mon Oct 21 13:32:13 2002 @@ -406,6 +406,22 @@ int $0x80 /* enter kernel with args */ 0: jmp 0b +#ifdef COMPAT_FREEBSD4 + ALIGN_TEXT +freebsd4_sigcode: + call *SIGF_HANDLER(%esp) /* call signal handler */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ + pushl %eax + testl $PSL_VM,UC4_EFLAGS(%eax) + jne 9f + movl UC4_GS(%eax),%gs /* restore %gs */ +9: + movl $344,%eax /* 4.x SYS_sigreturn */ + pushl %eax /* junk to fake return addr. */ + int $0x80 /* enter kernel with args */ +0: jmp 0b +#endif + #ifdef COMPAT_43 ALIGN_TEXT osigcode: @@ -416,7 +432,7 @@ jne 9f movl SC_GS(%eax),%gs /* restore %gs */ 9: - movl $SYS_osigreturn,%eax + movl $103,%eax /* 3.x SYS_sigreturn */ pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ 0: jmp 0b @@ -426,10 +442,16 @@ esigcode: .data - .globl szsigcode, szosigcode + .globl szsigcode szsigcode: .long esigcode-sigcode +#ifdef COMPAT_FREEBSD4 + .globl szfreebsd4_sigcode +szfreebsd4_sigcode: + .long esigcode-freebsd4_sigcode +#endif #ifdef COMPAT_43 + .globl szosigcode szosigcode: .long esigcode-osigcode #endif diff -ru3 ../../../sys/i386/i386/machdep.c sys/i386/i386/machdep.c --- ../../../sys/i386/i386/machdep.c Mon Oct 21 13:32:11 2002 +++ sys/i386/i386/machdep.c Mon Oct 21 13:44:29 2002 @@ -165,6 +165,10 @@ #ifdef COMPAT_43 static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); #endif +#ifdef COMPAT_FREEBSD4 +static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, + u_long code); +#endif static int sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) @@ -286,8 +290,7 @@ sigset_t *mask; u_long code; { - struct osigframe sf; - struct osigframe *fp; + struct osigframe sf, *fp; struct proc *p; struct thread *td; struct sigacts *psp; @@ -408,6 +411,129 @@ } #endif /* COMPAT_43 */ +#ifdef COMPAT_FREEBSD4 +static void +freebsd4_sendsig(catcher, sig, mask, code) + sig_t catcher; + int sig; + sigset_t *mask; + u_long code; +{ + struct sigframe4 sf, *sfp; + struct proc *p; + struct thread *td; + struct sigacts *psp; + struct trapframe *regs; + int oonstack; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + psp = p->p_sigacts; + regs = td->td_frame; + oonstack = sigonstack(regs->tf_esp); + + /* Save user context. */ + bzero(&sf, sizeof(sf)); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_stack = p->p_sigstk; + sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) + ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; + sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; + sf.sf_uc.uc_mcontext.mc_gs = rgs(); + bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); + + /* Allocate space for the signal handler context. */ + if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sfp = (struct sigframe4 *)(p->p_sigstk.ss_sp + + p->p_sigstk.ss_size - sizeof(struct sigframe4)); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + p->p_sigstk.ss_flags |= SS_ONSTACK; +#endif + } else + sfp = (struct sigframe4 *)regs->tf_esp - 1; + PROC_UNLOCK(p); + + /* Translate the signal if appropriate. */ + if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + + /* Build the argument list for the signal handler. */ + sf.sf_signum = sig; + sf.sf_ucontext = (register_t)&sfp->sf_uc; + PROC_LOCK(p); + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + /* Signal handler installed with SA_SIGINFO. */ + sf.sf_siginfo = (register_t)&sfp->sf_si; + sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; + + /* Fill in POSIX parts */ + sf.sf_si.si_signo = sig; + sf.sf_si.si_code = code; + sf.sf_si.si_addr = (void *)regs->tf_err; + sf.sf_si.si_pid = p->p_pid; + sf.sf_si.si_uid = p->p_ucred->cr_uid; + } else { + /* Old FreeBSD-style arguments. */ + sf.sf_siginfo = code; + sf.sf_addr = regs->tf_err; + sf.sf_ahu.sf_handler = catcher; + } + PROC_UNLOCK(p); + + /* + * If we're a vm86 process, we want to save the segment registers. + * We also change eflags to be our emulated eflags, not the actual + * eflags. + */ + if (regs->tf_eflags & PSL_VM) { + struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; + struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; + + sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; + sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; + sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; + sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; + + if (vm86->vm86_has_vme == 0) + sf.sf_uc.uc_mcontext.mc_eflags = + (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | + (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); + + /* + * Clear PSL_NT to inhibit T_TSSFLT faults on return from + * syscalls made by the signal handler. This just avoids + * wasting time for our lazy fixup of such faults. PSL_NT + * does nothing in vm86 mode, but vm86 programs can set it + * almost legitimately in probes for old cpu types. + */ + tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); + } + + /* + * Copy the sigframe out to the user's stack. + */ + if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { +#ifdef DEBUG + printf("process %ld has trashed its stack\n", (long)p->p_pid); +#endif + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + regs->tf_esp = (int)sfp; + regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode; + regs->tf_eflags &= ~PSL_T; + regs->tf_cs = _ucodesel; + regs->tf_ds = _udatasel; + regs->tf_es = _udatasel; + regs->tf_fs = _udatasel; + regs->tf_ss = _udatasel; + PROC_LOCK(p); +} +#endif /* COMPAT_FREEBSD4 */ + void sendsig(catcher, sig, mask, code) sig_t catcher; @@ -415,18 +541,23 @@ sigset_t *mask; u_long code; { - struct sigframe sf; + struct sigframe sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; - struct sigframe *sfp; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; +#ifdef COMPAT_FREEBSD4 + if (SIGISMEMBER(psp->ps_freebsd4, sig)) { + freebsd4_sendsig(catcher, sig, mask, code); + return; + } +#endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { osendsig(catcher, sig, mask, code); @@ -550,6 +681,7 @@ * * MPSAFE */ +#ifdef COMPAT_43 int osigreturn(td, uap) struct thread *td; @@ -557,7 +689,6 @@ struct osigcontext *sigcntxp; } */ *uap; { -#ifdef COMPAT_43 struct osigcontext sc; struct trapframe *regs; struct osigcontext *scp; @@ -662,10 +793,116 @@ signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); -#else /* !COMPAT_43 */ - return (ENOSYS); +} #endif /* COMPAT_43 */ + +#ifdef COMPAT_FREEBSD4 +/* + * MPSAFE + */ +int +freebsd4_sigreturn(td, uap) + struct thread *td; + struct freebsd4_sigreturn_args /* { + const ucontext4 *sigcntxp; + } */ *uap; +{ + struct ucontext4 uc; + struct proc *p = td->td_proc; + struct trapframe *regs; + const struct ucontext4 *ucp; + int cs, eflags, error; + + error = copyin(uap->sigcntxp, &uc, sizeof(uc)); + if (error != 0) + return (error); + ucp = &uc; + regs = td->td_frame; + eflags = ucp->uc_mcontext.mc_eflags; + if (eflags & PSL_VM) { + struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; + struct vm86_kernel *vm86; + + /* + * if pcb_ext == 0 or vm86_inited == 0, the user hasn't + * set up the vm86 area, and we can't enter vm86 mode. + */ + if (td->td_pcb->pcb_ext == 0) + return (EINVAL); + vm86 = &td->td_pcb->pcb_ext->ext_vm86; + if (vm86->vm86_inited == 0) + return (EINVAL); + + /* Go back to user mode if both flags are set. */ + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) + trapsignal(p, SIGBUS, 0); + + if (vm86->vm86_has_vme) { + eflags = (tf->tf_eflags & ~VME_USERCHANGE) | + (eflags & VME_USERCHANGE) | PSL_VM; + } else { + vm86->vm86_eflags = eflags; /* save VIF, VIP */ + eflags = (tf->tf_eflags & ~VM_USERCHANGE) | + (eflags & VM_USERCHANGE) | PSL_VM; + } + bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); + tf->tf_eflags = eflags; + tf->tf_vm86_ds = tf->tf_ds; + tf->tf_vm86_es = tf->tf_es; + tf->tf_vm86_fs = tf->tf_fs; + tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; + tf->tf_ds = _udatasel; + tf->tf_es = _udatasel; + tf->tf_fs = _udatasel; + } else { + /* + * Don't allow users to change privileged or reserved flags. + */ + /* + * XXX do allow users to change the privileged flag PSL_RF. + * The cpu sets PSL_RF in tf_eflags for faults. Debuggers + * should sometimes set it there too. tf_eflags is kept in + * the signal context during signal handling and there is no + * other place to remember it, so the PSL_RF bit may be + * corrupted by the signal handler without us knowing. + * Corruption of the PSL_RF bit at worst causes one more or + * one less debugger trap, so allowing it is fairly harmless. + */ + if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { + printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags); + return (EINVAL); + } + + /* + * Don't allow users to load a valid privileged %cs. Let the + * hardware check for invalid selectors, excess privilege in + * other selectors, invalid %eip's and invalid %esp's. + */ + cs = ucp->uc_mcontext.mc_cs; + if (!CS_SECURE(cs)) { + printf("freebsd4_sigreturn: cs = 0x%x\n", cs); + trapsignal(p, SIGBUS, T_PROTFLT); + return (EINVAL); + } + + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); + } + + PROC_LOCK(p); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + if (ucp->uc_mcontext.mc_onstack & 1) + p->p_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigstk.ss_flags &= ~SS_ONSTACK; +#endif + + p->p_sigmask = ucp->uc_sigmask; + SIG_CANTMASK(p->p_sigmask); + signotify(p); + PROC_UNLOCK(p); + return (EJUSTRETURN); } +#endif /* COMPAT_FREEBSD4 */ /* * MPSAFE @@ -2150,7 +2387,7 @@ #ifndef DEV_NPX mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; -#else /* DEV_NPX */ +#else union savefpu *addr; /* @@ -2180,9 +2417,8 @@ bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); } - bcopy(&mcp->mc_fpstate, &td->td_pcb->pcb_save, sizeof(mcp->mc_fpstate)); mcp->mc_fpformat = npxformat(); -#endif /* !DEV_NPX */ +#endif } static int @@ -2192,7 +2428,10 @@ if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); - if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) + else if (mcp->mc_fpformat != _MC_FPFMT_387 && + mcp->mc_fpformat != _MC_FPFMT_XMM) + return (EINVAL); + else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) /* We don't care what state is left in the FPU or PCB. */ fpstate_drop(td); else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || @@ -2215,25 +2454,14 @@ * be called with interrupts disabled. */ npxsetregs(td, addr); +#endif /* * Don't bother putting things back where they were in the * misaligned case, since we know that the caller won't use * them again. */ - } else { - /* - * There is no valid FPU state in *mcp, so use the saved - * state in the PCB if there is one. XXX the test for - * whether there is one seems to be quite broken. We - * forcibly drop the state in sendsig(). - */ - if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) != 0) - npxsetregs(td, &td->td_pcb->pcb_save); -#endif -#if !defined(COMPAT_FREEBSD4) && !defined(COMPAT_43) + } else return (EINVAL); -#endif - } return (0); } diff -ru3 ../../../sys/i386/include/md_var.h sys/i386/include/md_var.h --- ../../../sys/i386/include/md_var.h Thu Aug 29 21:21:40 2002 +++ sys/i386/include/md_var.h Mon Oct 14 19:13:53 2002 @@ -56,7 +56,13 @@ #endif extern void (*ovbcopy_vector)(const void *from, void *to, size_t len); extern char sigcode[]; -extern int szsigcode, szosigcode; +extern int szsigcode; +#ifdef COMPAT_FREEBSD4 +extern int szfreebsd4_sigcode; +#endif +#ifdef COMPAT_43 +extern int szosigcode; +#endif typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); struct thread; diff -ru3 ../../../sys/i386/include/sigframe.h sys/i386/include/sigframe.h --- ../../../sys/i386/include/sigframe.h Tue Feb 19 16:21:33 2002 +++ sys/i386/include/sigframe.h Mon Oct 21 13:32:13 2002 @@ -35,6 +35,7 @@ * Signal frames, arguments passed to application signal handlers. */ #ifdef _KERNEL +#ifdef COMPAT_43 struct osigframe { /* * The first four members may be used by applications. @@ -69,6 +70,23 @@ /* In the SA_SIGINFO case, sf_arg2 points here. */ osiginfo_t sf_siginfo; }; +#endif +#ifdef COMPAT_FREEBSD4 +/* FreeBSD 4.x */ +struct sigframe4 { + register_t sf_signum; + register_t sf_siginfo; /* code or pointer to sf_si */ + register_t sf_ucontext; /* points to sf_uc */ + register_t sf_addr; /* undocumented 4th arg */ + + union { + __siginfohandler_t *sf_action; + __sighandler_t *sf_handler; + } sf_ahu; + struct ucontext4 sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ +}; +#endif #endif struct sigframe { diff -ru3 ../../../sys/i386/include/signal.h sys/i386/include/signal.h --- ../../../sys/i386/include/signal.h Mon Oct 14 18:27:01 2002 +++ sys/i386/include/signal.h Fri Oct 25 11:43:31 2002 @@ -60,7 +60,7 @@ /* * Only the kernel should need these old type definitions. */ -#ifdef _KERNEL +#if defined(_KERNEL) && defined(COMPAT_43) /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following @@ -68,8 +68,6 @@ * to the handler to allow it to restore state properly if * a non-standard exit is performed. */ -typedef unsigned int osigset_t; - struct osigcontext { int sc_onstack; /* sigstack state to restore */ osigset_t sc_mask; /* signal mask to restore */ diff -ru3 ../../../sys/i386/include/ucontext.h sys/i386/include/ucontext.h --- ../../../sys/i386/include/ucontext.h Fri Oct 4 14:06:49 2002 +++ sys/i386/include/ucontext.h Mon Oct 21 13:32:13 2002 @@ -73,6 +73,34 @@ } mcontext_t; #ifdef _KERNEL +#ifdef COMPAT_FREEBSD4 +/* For 4.x binaries */ +struct mcontext4 { + int mc_onstack; /* XXX - sigcontext compat. */ + int mc_gs; + int mc_fs; + int mc_es; + int mc_ds; + int mc_edi; + int mc_esi; + int mc_ebp; + int mc_isp; + int mc_ebx; + int mc_edx; + int mc_ecx; + int mc_eax; + int mc_trapno; + int mc_err; + int mc_eip; + int mc_cs; + int mc_eflags; + int mc_esp; /* machine state */ + int mc_ss; + int mc_fpregs[28]; /* env87 + fpacc87 + u_long */ + int __spare__[17]; +}; +#endif + struct thread; void get_mcontext(struct thread *td, mcontext_t *mcp); diff -ru3 ../../../sys/i386/isa/npx.c sys/i386/isa/npx.c --- ../../../sys/i386/isa/npx.c Mon Oct 21 13:32:11 2002 +++ sys/i386/isa/npx.c Thu Oct 24 22:55:28 2002 @@ -1003,6 +1003,7 @@ intr_restore(s); bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr)); } + curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE; } static void diff -ru3 ../../../sys/ia64/ia64/machdep.c sys/ia64/ia64/machdep.c --- ../../../sys/ia64/ia64/machdep.c Thu Oct 24 22:55:22 2002 +++ sys/ia64/ia64/machdep.c Thu Oct 24 22:55:28 2002 @@ -951,18 +951,6 @@ } /* - * Stub to satisfy the reference to osigreturn in the syscall table. This - * is needed even for newer arches that don't support old signals because - * the syscall table is machine-independent. - */ -int -osigreturn(struct thread *td, struct osigreturn_args *uap) -{ - - return (nosys(td, (struct nosys_args *)uap)); -} - -/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). @@ -1068,6 +1056,15 @@ #endif return (EJUSTRETURN); } + +#ifdef COMPAT_FREEBSD4 +int +freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) +{ + + return sigreturn(td, (struct sigreturn_args *)uap); +} +#endif /* * Machine dependent boot() routine diff -ru3 ../../../sys/ia64/include/sigframe.h sys/ia64/include/sigframe.h --- ../../../sys/ia64/include/sigframe.h Tue Sep 4 19:12:20 2001 +++ sys/ia64/include/sigframe.h Thu Oct 17 14:18:07 2002 @@ -31,9 +31,6 @@ #ifndef _MACHINE_SIGFRAME_H_ #define _MACHINE_SIGFRAME_H_ 1 -struct osigframe { -}; - struct sigframe { ucontext_t sf_uc; siginfo_t sf_si; diff -ru3 ../../../sys/ia64/include/signal.h sys/ia64/include/signal.h --- ../../../sys/ia64/include/signal.h Mon Oct 14 18:27:01 2002 +++ sys/ia64/include/signal.h Mon Oct 14 20:44:50 2002 @@ -70,7 +70,6 @@ #endif #endif -#ifdef _KERNEL /* * Information pushed on stack when a signal is delivered. @@ -82,12 +81,6 @@ * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline * representations of 'struct reg' and 'struct fpreg', respectively. */ -typedef unsigned int osigset_t; -struct osigcontext { - int _not_used; -}; - -#endif /* !_KERNEL */ #if __BSD_VISIBLE /* diff -ru3 ../../../sys/kern/init_sysent.c sys/kern/init_sysent.c --- ../../../sys/kern/init_sysent.c Wed Oct 23 13:23:49 2002 +++ sys/kern/init_sysent.c Wed Oct 23 13:29:03 2002 @@ -131,7 +131,7 @@ { SYF_MPSAFE | AS(getpriority_args), (sy_call_t *)getpriority }, /* 100 = getpriority */ { compat(SYF_MPSAFE | AS(osend_args),send) }, /* 101 = old send */ { compat(SYF_MPSAFE | AS(orecv_args),recv) }, /* 102 = old recv */ - { SYF_MPSAFE | AS(osigreturn_args), (sy_call_t *)osigreturn }, /* 103 = osigreturn */ + { compat(SYF_MPSAFE | AS(osigreturn_args),sigreturn) }, /* 103 = old sigreturn */ { SYF_MPSAFE | AS(bind_args), (sy_call_t *)bind }, /* 104 = bind */ { SYF_MPSAFE | AS(setsockopt_args), (sy_call_t *)setsockopt }, /* 105 = setsockopt */ { SYF_MPSAFE | AS(listen_args), (sy_call_t *)listen }, /* 106 = listen */ @@ -370,9 +370,9 @@ { 0, (sy_call_t *)nosys }, /* 339 = pioctl */ { SYF_MPSAFE | AS(sigprocmask_args), (sy_call_t *)sigprocmask }, /* 340 = sigprocmask */ { SYF_MPSAFE | AS(sigsuspend_args), (sy_call_t *)sigsuspend }, /* 341 = sigsuspend */ - { SYF_MPSAFE | AS(sigaction_args), (sy_call_t *)sigaction }, /* 342 = sigaction */ + { compat4(SYF_MPSAFE | AS(freebsd4_sigaction_args),sigaction) }, /* 342 = old sigaction */ { SYF_MPSAFE | AS(sigpending_args), (sy_call_t *)sigpending }, /* 343 = sigpending */ - { SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn }, /* 344 = sigreturn */ + { compat4(SYF_MPSAFE | AS(freebsd4_sigreturn_args),sigreturn) }, /* 344 = old sigreturn */ { 0, (sy_call_t *)nosys }, /* 345 = sigtimedwait */ { 0, (sy_call_t *)nosys }, /* 346 = sigwaitinfo */ { SYF_MPSAFE | AS(__acl_get_file_args), (sy_call_t *)__acl_get_file }, /* 347 = __acl_get_file */ @@ -444,8 +444,8 @@ { AS(extattr_get_link_args), (sy_call_t *)extattr_get_link }, /* 413 = extattr_get_link */ { AS(extattr_delete_link_args), (sy_call_t *)extattr_delete_link }, /* 414 = extattr_delete_link */ { 0, (sy_call_t *)nosys }, /* 415 = __execve_mac */ - { 0, (sy_call_t *)nosys }, /* 416 = newsigreturn */ - { 0, (sy_call_t *)nosys }, /* 417 = newsigaction */ + { SYF_MPSAFE | AS(sigaction_args), (sy_call_t *)sigaction }, /* 416 = sigaction */ + { SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn }, /* 417 = sigreturn */ { 0, (sy_call_t *)nosys }, /* 418 = __xstat */ { 0, (sy_call_t *)nosys }, /* 419 = __xfstat */ { 0, (sy_call_t *)nosys }, /* 420 = __xlstat */ diff -ru3 ../../../sys/kern/kern_sig.c sys/kern/kern_sig.c --- ../../../sys/kern/kern_sig.c Thu Oct 3 11:32:03 2002 +++ sys/kern/kern_sig.c Wed Oct 23 18:14:04 2002 @@ -73,6 +73,13 @@ #include +#if !defined(COMPAT_FREEBSD4) && !defined(NO_COMPAT_FREEBSD4) +#error "You *really* want COMPAT_FREEBSD4 on -current for a while" +#endif +#if defined (__alpha__) && !defined(COMPAT_43) +#error "You *really* need COMPAT_43 on the alpha for longjmp(3)" +#endif + #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ static int coredump(struct thread *); @@ -229,14 +236,15 @@ /* * kern_sigaction * sigaction + * freebsd4_sigaction * osigaction */ int -kern_sigaction(td, sig, act, oact, old) +kern_sigaction(td, sig, act, oact, flags) struct thread *td; register int sig; struct sigaction *act, *oact; - int old; + int flags; { register struct sigacts *ps; struct proc *p = td->td_proc; @@ -353,9 +361,18 @@ else SIGADDSET(p->p_sigcatch, sig); } +#ifdef COMPAT_FREEBSD4 + if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || + ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || + (flags & KSA_FREEBSD4) == 0) + SIGDELSET(ps->ps_freebsd4, sig); + else + SIGADDSET(ps->ps_freebsd4, sig); +#endif #ifdef COMPAT_43 if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || - ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || !old) + ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || + (flags & KSA_OSIGSET) == 0) SIGDELSET(ps->ps_osigset, sig); else SIGADDSET(ps->ps_osigset, sig); @@ -403,6 +420,46 @@ return (error); } +#ifdef COMPAT_FREEBSD4 +#ifndef _SYS_SYSPROTO_H_ +struct freebsd4_sigaction_args { + int sig; + struct sigaction *act; + struct sigaction *oact; +}; +#endif +/* + * MPSAFE + */ +/* ARGSUSED */ +int +freebsd4_sigaction(td, uap) + struct thread *td; + register struct freebsd4_sigaction_args *uap; +{ + struct sigaction act, oact; + register struct sigaction *actp, *oactp; + int error; + + mtx_lock(&Giant); + + actp = (uap->act != NULL) ? &act : NULL; + oactp = (uap->oact != NULL) ? &oact : NULL; + if (actp) { + error = copyin(uap->act, actp, sizeof(act)); + if (error) + goto done2; + } + error = kern_sigaction(td, uap->sig, actp, oactp, KSA_FREEBSD4); + if (oactp && !error) { + error = copyout(oactp, uap->oact, sizeof(oact)); + } +done2: + mtx_unlock(&Giant); + return (error); +} +#endif /* COMAPT_FREEBSD4 */ + #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigaction_args { @@ -441,7 +498,7 @@ nsap->sa_flags = sa.sa_flags; OSIG2SIG(sa.sa_mask, nsap->sa_mask); } - error = kern_sigaction(td, uap->signum, nsap, osap, 1); + error = kern_sigaction(td, uap->signum, nsap, osap, KSA_OSIGSET); if (osap && !error) { sa.sa_handler = osap->sa_handler; sa.sa_flags = osap->sa_flags; @@ -452,6 +509,18 @@ mtx_unlock(&Giant); return (error); } + +#if !defined(__i386__) && !defined(__alpha__) +/* Avoid replicating the same stub everywhere */ +int +osigreturn(td, uap) + struct thread *td; + struct osigreturn_args *uap; +{ + + return (nosys(td, (struct nosys_args *)uap)); +} +#endif #endif /* COMPAT_43 */ /* diff -ru3 ../../../sys/kern/syscalls.c sys/kern/syscalls.c --- ../../../sys/kern/syscalls.c Wed Oct 23 13:23:50 2002 +++ sys/kern/syscalls.c Wed Oct 23 13:29:03 2002 @@ -110,7 +110,7 @@ "getpriority", /* 100 = getpriority */ "old.send", /* 101 = old send */ "old.recv", /* 102 = old recv */ - "osigreturn", /* 103 = osigreturn */ + "old.sigreturn", /* 103 = old sigreturn */ "bind", /* 104 = bind */ "setsockopt", /* 105 = setsockopt */ "listen", /* 106 = listen */ @@ -349,9 +349,9 @@ "#339", /* 339 = pioctl */ "sigprocmask", /* 340 = sigprocmask */ "sigsuspend", /* 341 = sigsuspend */ - "sigaction", /* 342 = sigaction */ + "old.sigaction", /* 342 = old sigaction */ "sigpending", /* 343 = sigpending */ - "sigreturn", /* 344 = sigreturn */ + "old.sigreturn", /* 344 = old sigreturn */ "#345", /* 345 = sigtimedwait */ "#346", /* 346 = sigwaitinfo */ "__acl_get_file", /* 347 = __acl_get_file */ @@ -423,8 +423,8 @@ "extattr_get_link", /* 413 = extattr_get_link */ "extattr_delete_link", /* 414 = extattr_delete_link */ "#415", /* 415 = __execve_mac */ - "#416", /* 416 = newsigreturn */ - "#417", /* 417 = newsigaction */ + "sigaction", /* 416 = sigaction */ + "sigreturn", /* 417 = sigreturn */ "#418", /* 418 = __xstat */ "#419", /* 419 = __xfstat */ "#420", /* 420 = __xlstat */ diff -ru3 ../../../sys/kern/syscalls.master sys/kern/syscalls.master --- ../../../sys/kern/syscalls.master Wed Oct 23 13:23:50 2002 +++ sys/kern/syscalls.master Wed Oct 23 13:29:03 2002 @@ -175,7 +175,7 @@ 100 MSTD BSD { int getpriority(int which, int who); } 101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); } 102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); } -103 MSTD BSD { int osigreturn(struct osigcontext *sigcntxp); } +103 MCOMPAT BSD { int sigreturn(struct osigcontext *sigcntxp); } 104 MSTD BSD { int bind(int s, caddr_t name, int namelen); } 105 MSTD BSD { int setsockopt(int s, int level, int name, \ caddr_t val, int valsize); } @@ -490,10 +490,10 @@ 340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \ sigset_t *oset); } 341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); } -342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \ +342 MCOMPAT4 POSIX { int sigaction(int sig, const struct sigaction *act, \ struct sigaction *oact); } 343 MSTD POSIX { int sigpending(sigset_t *set); } -344 MSTD BSD { int sigreturn(const struct __ucontext *sigcntxp); } +344 MCOMPAT4 BSD { int sigreturn(const struct ucontext4 *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo 347 MSTD BSD { int __acl_get_file(const char *path, \ @@ -601,8 +601,9 @@ 414 STD BSD { int extattr_delete_link(const char *path, \ int attrnamespace, const char *attrname); } 415 UNIMPL BSD __execve_mac -416 UNIMPL BSD newsigreturn -417 UNIMPL BSD newsigaction +416 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \ + struct sigaction *oact); } +417 MSTD BSD { int sigreturn(const struct __ucontext *sigcntxp); } 418 UNIMPL BSD __xstat 419 UNIMPL BSD __xfstat 420 UNIMPL BSD __xlstat diff -ru3 ../../../sys/powerpc/include/signal.h sys/powerpc/include/signal.h --- ../../../sys/powerpc/include/signal.h Mon Oct 14 18:27:02 2002 +++ sys/powerpc/include/signal.h Mon Oct 14 20:44:50 2002 @@ -44,28 +44,7 @@ typedef int sig_atomic_t; #ifdef _KERNEL -typedef unsigned int osigset_t; - #include - -/* - * XXX why do we have compatibility structs for a new platform? - */ -#if defined(__LIBC12_SOURCE__) || defined(_KERNEL) -struct sigcontext13 { - int sc_onstack; /* saved onstack flag */ - int sc_mask; /* saved signal mask (old style) */ - struct trapframe sc_frame; /* saved registers */ -}; -#endif /* __LIBC12_SOURCE__ || _KERNEL */ - -struct osigcontext { - int sc_onstack; /* saved onstack flag */ - int __sc_mask13; /* saved signal mask (old style) */ - struct trapframe sc_frame; /* saved registers */ - struct __sigset sc_mask; /* saved signal mask (new style) */ -}; - #endif /* _KERNEL */ #if __BSD_VISIBLE diff -ru3 ../../../sys/powerpc/powerpc/machdep.c sys/powerpc/powerpc/machdep.c --- ../../../sys/powerpc/powerpc/machdep.c Fri Sep 20 17:31:47 2002 +++ sys/powerpc/powerpc/machdep.c Thu Oct 17 14:31:36 2002 @@ -598,18 +598,6 @@ PROC_LOCK(p); } -/* - * Stub to satisfy the reference to osigreturn in the syscall table. This - * is needed even for newer arches that don't support old signals because - * the syscall table is machine-independent. - */ -int -osigreturn(struct thread *td, struct osigreturn_args *uap) -{ - - return (nosys(td, (struct nosys_args *)uap)); -} - int sigreturn(struct thread *td, struct sigreturn_args *uap) { @@ -655,6 +643,15 @@ return (EJUSTRETURN); } + +#ifdef COMPAT_FREEBSD4 +int +freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) +{ + + return sigreturn(td, (struct sigreturn_args *)uap); +} +#endif void cpu_boot(int howto) diff -ru3 ../../../sys/sparc64/include/signal.h sys/sparc64/include/signal.h --- ../../../sys/sparc64/include/signal.h Mon Oct 14 18:27:02 2002 +++ sys/sparc64/include/signal.h Mon Oct 14 20:44:50 2002 @@ -46,14 +46,6 @@ #define MINSIGSTKSZ (1024 * 4) #endif -#ifdef _KERNEL -typedef int osigset_t; - -struct osigcontext { - int dummy; -}; -#endif - #if __BSD_VISIBLE struct sigcontext { int _dummy; diff -ru3 ../../../sys/sparc64/sparc64/machdep.c sys/sparc64/sparc64/machdep.c --- ../../../sys/sparc64/sparc64/machdep.c Wed Oct 23 13:23:51 2002 +++ sys/sparc64/sparc64/machdep.c Wed Oct 23 13:29:03 2002 @@ -40,6 +40,7 @@ * $FreeBSD: src/sys/sparc64/sparc64/machdep.c,v 1.66 2002/10/22 18:03:15 jake Exp $ */ +#include "opt_compat.h" #include "opt_ddb.h" #include "opt_msgbuf.h" @@ -448,20 +449,6 @@ PROC_LOCK(p); } -/* - * Stub to satisfy the reference to osigreturn in the syscall table. This - * is needed even for newer arches that don't support old signals because - * the syscall table is machine-independent. - * - * MPSAFE - */ -int -osigreturn(struct thread *td, struct osigreturn_args *uap) -{ - - return (nosys(td, (struct nosys_args *)uap)); -} - #ifndef _SYS_SYSPROTO_H_ struct sigreturn_args { ucontext_t *ucp; @@ -504,6 +491,15 @@ td->td_frame->tf_tstate); return (EJUSTRETURN); } + +#ifdef COMPAT_FREEBSD4 +int +freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) +{ + + return sigreturn(td, (struct sigreturn_args *)uap); +} +#endif /* * Exit the kernel and execute a firmware call that will not return, as diff -ru3 ../../../sys/sys/_sigset.h sys/sys/_sigset.h --- ../../../sys/sys/_sigset.h Mon Oct 7 11:57:40 2002 +++ sys/sys/_sigset.h Fri Oct 25 11:43:31 2002 @@ -56,4 +56,8 @@ __uint32_t __bits[_SIG_WORDS]; } __sigset_t; +#if defined(_KERNEL) && defined(COMPAT_43) +typedef unsigned int osigset_t; +#endif + #endif /* !_SYS__SIGSET_H_ */ diff -ru3 ../../../sys/sys/signal.h sys/sys/signal.h --- ../../../sys/sys/signal.h Mon Oct 14 18:27:02 2002 +++ sys/sys/signal.h Fri Oct 25 11:43:31 2002 @@ -302,6 +302,14 @@ #define sv_onstack sv_flags /* isn't compatibility wonderful! */ #endif +/* Keep this in one place only */ +#if defined(_KERNEL) && defined(COMPAT_43) && \ + !defined(__i386__) && !defined(__alpha__) +struct osigcontext { + int _not_used; +}; +#endif + #if __XSI_VISIBLE /* * Structure used in sigstack call. diff -ru3 ../../../sys/sys/signalvar.h sys/sys/signalvar.h --- ../../../sys/sys/signalvar.h Wed Oct 23 13:23:51 2002 +++ sys/sys/signalvar.h Wed Oct 23 18:14:04 2002 @@ -56,11 +56,12 @@ sigset_t ps_sigreset; /* signals that reset when caught */ sigset_t ps_signodefer; /* signals not masked while handled */ sigset_t ps_siginfo; /* signals that want SA_SIGINFO args */ - sigset_t ps_osigset; /* signals that use osigset_t */ + sigset_t ps_freebsd4; /* signals that use freebsd4 ucontext */ + sigset_t ps_osigset; /* signals that use <= 3.x osigset_t */ sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX */ }; -#ifdef _KERNEL +#if defined(_KERNEL) && defined(COMPAT_43) /* * Compatibility. */ @@ -81,7 +82,7 @@ }; typedef void __osiginfohandler_t(int, osiginfo_t *, void *); -#endif /* _KERNEL */ +#endif /* _KERNEL && COMPAT_43 */ /* additional signal action values, used only temporarily/internally */ #define SIG_CATCH ((__sighandler_t *)2) diff -ru3 ../../../sys/sys/syscall.h sys/sys/syscall.h --- ../../../sys/sys/syscall.h Wed Oct 23 13:23:51 2002 +++ sys/sys/syscall.h Wed Oct 23 13:29:03 2002 @@ -107,7 +107,7 @@ #define SYS_getpriority 100 /* 101 is old send */ /* 102 is old recv */ -#define SYS_osigreturn 103 + /* 103 is old sigreturn */ #define SYS_bind 104 #define SYS_setsockopt 105 #define SYS_listen 106 @@ -265,9 +265,9 @@ #define SYS_jail 338 #define SYS_sigprocmask 340 #define SYS_sigsuspend 341 -#define SYS_sigaction 342 + /* 342 is old sigaction */ #define SYS_sigpending 343 -#define SYS_sigreturn 344 + /* 344 is old sigreturn */ #define SYS___acl_get_file 347 #define SYS___acl_set_file 348 #define SYS___acl_get_fd 349 @@ -323,4 +323,6 @@ #define SYS_extattr_set_link 412 #define SYS_extattr_get_link 413 #define SYS_extattr_delete_link 414 +#define SYS_sigaction 416 +#define SYS_sigreturn 417 #define SYS_MAXSYSCALL 421 diff -ru3 ../../../sys/sys/syscall.mk sys/sys/syscall.mk --- ../../../sys/sys/syscall.mk Wed Oct 23 13:23:51 2002 +++ sys/sys/syscall.mk Wed Oct 23 13:29:03 2002 @@ -82,7 +82,6 @@ socket.o \ connect.o \ getpriority.o \ - osigreturn.o \ bind.o \ setsockopt.o \ listen.o \ @@ -214,9 +213,7 @@ jail.o \ sigprocmask.o \ sigsuspend.o \ - sigaction.o \ sigpending.o \ - sigreturn.o \ __acl_get_file.o \ __acl_set_file.o \ __acl_get_fd.o \ @@ -271,4 +268,6 @@ __mac_set_link.o \ extattr_set_link.o \ extattr_get_link.o \ - extattr_delete_link.o + extattr_delete_link.o \ + sigaction.o \ + sigreturn.o diff -ru3 ../../../sys/sys/syscallsubr.h sys/sys/syscallsubr.h --- ../../../sys/sys/syscallsubr.h Mon Sep 9 16:44:40 2002 +++ sys/sys/syscallsubr.h Mon Oct 14 19:46:49 2002 @@ -67,7 +67,7 @@ int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, fd_set *fd_ex, struct timeval *tvp); int kern_sigaction(struct thread *td, int sig, struct sigaction *act, - struct sigaction *oact, int old); + struct sigaction *oact, int flags); int kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss); int kern_sigsuspend(struct thread *td, sigset_t mask); int kern_symlink(struct thread *td, char *path, char *link, @@ -77,5 +77,9 @@ int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg); int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); + +/* flags for kern_sigaction */ +#define KSA_OSIGSET 0x0001 /* uses osigact_t */ +#define KSA_FREEBSD4 0x0002 /* uses ucontext4 */ #endif /* !_SYS_SYSCALLSUBR_H_ */ diff -ru3 ../../../sys/sys/sysproto.h sys/sys/sysproto.h --- ../../../sys/sys/sysproto.h Wed Oct 23 13:23:51 2002 +++ sys/sys/sysproto.h Wed Oct 23 13:29:03 2002 @@ -361,9 +361,6 @@ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; }; -struct osigreturn_args { - char sigcntxp_l_[PADL_(struct osigcontext *)]; struct osigcontext * sigcntxp; char sigcntxp_r_[PADR_(struct osigcontext *)]; -}; struct bind_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; @@ -923,17 +920,9 @@ struct sigsuspend_args { char sigmask_l_[PADL_(const sigset_t *)]; const sigset_t * sigmask; char sigmask_r_[PADR_(const sigset_t *)]; }; -struct sigaction_args { - char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; - char act_l_[PADL_(const struct sigaction *)]; const struct sigaction * act; char act_r_[PADR_(const struct sigaction *)]; - char oact_l_[PADL_(struct sigaction *)]; struct sigaction * oact; char oact_r_[PADR_(struct sigaction *)]; -}; struct sigpending_args { char set_l_[PADL_(sigset_t *)]; sigset_t * set; char set_r_[PADR_(sigset_t *)]; }; -struct sigreturn_args { - char sigcntxp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct __ucontext *)]; -}; struct __acl_get_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; @@ -1188,6 +1177,14 @@ char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; }; +struct sigaction_args { + char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; + char act_l_[PADL_(const struct sigaction *)]; const struct sigaction * act; char act_r_[PADR_(const struct sigaction *)]; + char oact_l_[PADL_(struct sigaction *)]; struct sigaction * oact; char oact_r_[PADR_(struct sigaction *)]; +}; +struct sigreturn_args { + char sigcntxp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct __ucontext *)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_exit(struct thread *, struct sys_exit_args *); int fork(struct thread *, struct fork_args *); @@ -1267,7 +1264,6 @@ int socket(struct thread *, struct socket_args *); int connect(struct thread *, struct connect_args *); int getpriority(struct thread *, struct getpriority_args *); -int osigreturn(struct thread *, struct osigreturn_args *); int bind(struct thread *, struct bind_args *); int setsockopt(struct thread *, struct setsockopt_args *); int listen(struct thread *, struct listen_args *); @@ -1397,9 +1393,7 @@ int jail(struct thread *, struct jail_args *); int sigprocmask(struct thread *, struct sigprocmask_args *); int sigsuspend(struct thread *, struct sigsuspend_args *); -int sigaction(struct thread *, struct sigaction_args *); int sigpending(struct thread *, struct sigpending_args *); -int sigreturn(struct thread *, struct sigreturn_args *); int __acl_get_file(struct thread *, struct __acl_get_file_args *); int __acl_set_file(struct thread *, struct __acl_set_file_args *); int __acl_get_fd(struct thread *, struct __acl_get_fd_args *); @@ -1456,6 +1450,8 @@ int extattr_set_link(struct thread *, struct extattr_set_link_args *); int extattr_get_link(struct thread *, struct extattr_get_link_args *); int extattr_delete_link(struct thread *, struct extattr_delete_link_args *); +int sigaction(struct thread *, struct sigaction_args *); +int sigreturn(struct thread *, struct sigreturn_args *); #ifdef COMPAT_43 @@ -1523,6 +1519,9 @@ char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; +struct osigreturn_args { + char sigcntxp_l_[PADL_(struct osigcontext *)]; struct osigcontext * sigcntxp; char sigcntxp_r_[PADR_(struct osigcontext *)]; +}; struct osigvec_args { char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; char nsv_l_[PADL_(struct sigvec *)]; struct sigvec * nsv; char nsv_r_[PADR_(struct sigvec *)]; @@ -1602,6 +1601,7 @@ int oaccept(struct thread *, struct accept_args *); int osend(struct thread *, struct osend_args *); int orecv(struct thread *, struct orecv_args *); +int osigreturn(struct thread *, struct osigreturn_args *); int osigvec(struct thread *, struct osigvec_args *); int osigblock(struct thread *, struct osigblock_args *); int osigsetmask(struct thread *, struct osigsetmask_args *); @@ -1636,7 +1636,17 @@ char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; +struct freebsd4_sigaction_args { + char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; + char act_l_[PADL_(const struct sigaction *)]; const struct sigaction * act; char act_r_[PADR_(const struct sigaction *)]; + char oact_l_[PADL_(struct sigaction *)]; struct sigaction * oact; char oact_r_[PADR_(struct sigaction *)]; +}; +struct freebsd4_sigreturn_args { + char sigcntxp_l_[PADL_(const struct ucontext4 *)]; const struct ucontext4 * sigcntxp; char sigcntxp_r_[PADR_(const struct ucontext4 *)]; +}; int freebsd4_sendfile(struct thread *, struct freebsd4_sendfile_args *); +int freebsd4_sigaction(struct thread *, struct freebsd4_sigaction_args *); +int freebsd4_sigreturn(struct thread *, struct freebsd4_sigreturn_args *); #endif /* COMPAT_FREEBSD4 */ diff -ru3 ../../../sys/sys/ucontext.h sys/sys/ucontext.h --- ../../../sys/sys/ucontext.h Mon Sep 16 18:57:32 2002 +++ sys/sys/ucontext.h Mon Oct 21 13:32:14 2002 @@ -53,6 +53,20 @@ int __spare__[4]; } ucontext_t; +#if defined(_KERNEL) && defined(COMPAT_FREEBSD4) +#if defined(__i386__) || defined(__alpha__) +struct ucontext4 { + sigset_t uc_sigmask; + struct mcontext4 uc_mcontext; + struct ucontext4 *uc_link; + stack_t uc_stack; + int __spare__[8]; +}; +#else /* __i386__ || __alpha__ */ +#define ucontext4 ucontext +#endif /* __i386__ || __alpha__ */ +#endif /* _KERNEL */ + #ifndef _KERNEL __BEGIN_DECLS