From 23eeeff7bee66bd81fa2d7ec9d648339bd0d041f Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Fri, 25 Oct 2002 19:10:58 +0000 Subject: Split 4.x and 5.x signal handling so that we can keep 4.x signal handling clean and functional as 5.x evolves. This allows some of the nasty bandaids in the 5.x codepaths to be unwound. Encapsulate 4.x signal handling under COMPAT_FREEBSD4 (there is an anti-foot-shooting measure in place, 5.x folks need this for a while) and finish encapsulating the older stuff under COMPAT_43. Since the ancient stuff is required on alpha (longjmp(3) passes a 'struct osigcontext *' to the current sigreturn(2), instead of the 'ucontext_t *' that sigreturn is supposed to take), add a compile time check to prevent foot shooting there too. Add uniform COMPAT_43 stubs for ia64/sparc64/powerpc. Tested on: i386, alpha, ia64. Compiled on sparc64 (a few days ago). Approved by: re --- sys/alpha/alpha/locore.s | 52 +++++++- sys/alpha/alpha/machdep.c | 217 +++++++++++++++++++++++++++++++-- sys/alpha/include/md_var.h | 6 + sys/alpha/include/sigframe.h | 10 +- sys/alpha/include/signal.h | 4 +- sys/alpha/include/ucontext.h | 12 ++ sys/alpha/osf1/osf1_signal.c | 11 +- sys/amd64/amd64/genassym.c | 9 ++ sys/amd64/amd64/locore.S | 26 +++- sys/amd64/amd64/locore.s | 26 +++- sys/amd64/amd64/machdep.c | 276 ++++++++++++++++++++++++++++++++++++++---- sys/amd64/include/md_var.h | 8 +- sys/amd64/include/sigframe.h | 18 +++ sys/amd64/include/signal.h | 4 +- sys/amd64/include/ucontext.h | 28 +++++ sys/conf/options | 1 + sys/i386/i386/genassym.c | 9 ++ sys/i386/i386/locore.s | 26 +++- sys/i386/i386/machdep.c | 276 ++++++++++++++++++++++++++++++++++++++---- sys/i386/include/md_var.h | 8 +- sys/i386/include/sigframe.h | 18 +++ sys/i386/include/signal.h | 4 +- sys/i386/include/ucontext.h | 28 +++++ sys/ia64/ia64/machdep.c | 21 ++-- sys/ia64/include/sigframe.h | 3 - sys/ia64/include/signal.h | 7 -- sys/kern/init_sysent.c | 10 +- sys/kern/kern_sig.c | 77 +++++++++++- sys/kern/syscalls.c | 10 +- sys/kern/syscalls.master | 11 +- sys/powerpc/aim/machdep.c | 21 ++-- sys/powerpc/include/signal.h | 21 ---- sys/powerpc/powerpc/machdep.c | 21 ++-- sys/sparc64/include/signal.h | 8 -- sys/sparc64/sparc64/machdep.c | 24 ++-- sys/sys/_sigset.h | 4 + sys/sys/signal.h | 8 ++ sys/sys/signalvar.h | 7 +- sys/sys/syscall.h | 8 +- sys/sys/syscall.mk | 7 +- sys/sys/syscallsubr.h | 6 +- sys/sys/sysproto.h | 38 +++--- sys/sys/ucontext.h | 14 +++ 43 files changed, 1182 insertions(+), 221 deletions(-) (limited to 'sys') diff --git a/sys/alpha/alpha/locore.s b/sys/alpha/alpha/locore.s index 5d1cdce312ec..e5a7f654dc2e 100644 --- a/sys/alpha/alpha/locore.s +++ b/sys/alpha/alpha/locore.s @@ -53,6 +53,8 @@ * rights to redistribute these changes. */ +#include "opt_compat.h" + #include #include #include @@ -190,15 +192,55 @@ NESTED(sigcode,0,0,ra,0,0) 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 --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index db64fd3cf1de..888eb42e0966 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -232,6 +232,10 @@ SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, ""); #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 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) /* * 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 @@ 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) +{ + 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 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 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 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) /* * 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 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) * * 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 @@ osigreturn(struct thread *td, 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 @@ sigreturn(struct thread *td, struct pcb *pcb; unsigned long val; struct proc *p; + int error; ucp = uap->sigcntxp; pcb = td->td_pcb; @@ -1507,21 +1705,22 @@ sigreturn(struct thread *td, 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 --git a/sys/alpha/include/md_var.h b/sys/alpha/include/md_var.h index b59cb7df5178..12df6141c882 100644 --- a/sys/alpha/include/md_var.h +++ b/sys/alpha/include/md_var.h @@ -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 --git a/sys/alpha/include/sigframe.h b/sys/alpha/include/sigframe.h index eb8039b8532a..01196e569e83 100644 --- a/sys/alpha/include/sigframe.h +++ b/sys/alpha/include/sigframe.h @@ -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 --git a/sys/alpha/include/signal.h b/sys/alpha/include/signal.h index da32b41cbcf8..2a1f17b9b2d5 100644 --- a/sys/alpha/include/signal.h +++ b/sys/alpha/include/signal.h @@ -47,7 +47,7 @@ typedef long sig_atomic_t; /* * 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 @@ typedef long sig_atomic_t; * 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 --git a/sys/alpha/include/ucontext.h b/sys/alpha/include/ucontext.h index 3e8888143853..bfc18df8f42f 100644 --- a/sys/alpha/include/ucontext.h +++ b/sys/alpha/include/ucontext.h @@ -50,4 +50,16 @@ typedef struct __mcontext { 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 --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c index 7ea80fd8a2b6..b16c2c807abe 100644 --- a/sys/alpha/osf1/osf1_signal.c +++ b/sys/alpha/osf1/osf1_signal.c @@ -33,6 +33,11 @@ * $FreeBSD$ */ +#include "opt_compat.h" +#ifndef COMPAT_43 +#error "COMPAT_OSF1 requires COMPAT_43" +#endif + #include #include #include @@ -101,7 +106,6 @@ static void osf1_to_bsd_sigaction(const struct osf1_sigaction *osa, #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 @@ osf1_sigreturn(struct thread *td, 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 @@ osf1_osigstack(td, uap) /* 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 --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index d4aa9e3da060..5a8cf704dd22 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -37,6 +37,7 @@ * $FreeBSD$ */ +#include "opt_compat.h" #include "opt_kstack_pages.h" #include @@ -151,12 +152,20 @@ ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); 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 --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S index 5d5b39ed5fd9..8f1d801268b3 100644 --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -406,6 +406,22 @@ NON_GPROF_ENTRY(sigcode) 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 @@ osigcode: 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 @@ osigcode: 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 --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s index 5d5b39ed5fd9..8f1d801268b3 100644 --- a/sys/amd64/amd64/locore.s +++ b/sys/amd64/amd64/locore.s @@ -406,6 +406,22 @@ NON_GPROF_ENTRY(sigcode) 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 @@ osigcode: 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 @@ osigcode: 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 --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 80805a2048c5..ff69b568be79 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -165,6 +165,10 @@ int cold = 1; #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 @@ osendsig(catcher, sig, mask, code) 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 @@ osendsig(catcher, sig, mask, code) } #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 @@ sendsig(catcher, sig, mask, code) 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 @@ sendsig(catcher, sig, mask, code) * * MPSAFE */ +#ifdef COMPAT_43 int osigreturn(td, uap) struct thread *td; @@ -557,7 +689,6 @@ osigreturn(td, uap) struct osigcontext *sigcntxp; } */ *uap; { -#ifdef COMPAT_43 struct osigcontext sc; struct trapframe *regs; struct osigcontext *scp; @@ -662,10 +793,116 @@ osigreturn(td, uap) 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 @@ -2162,7 +2399,7 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) #ifndef DEV_NPX mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; -#else /* DEV_NPX */ +#else union savefpu *addr; /* @@ -2192,9 +2429,8 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) 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 @@ -2204,7 +2440,10 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) 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 || @@ -2227,25 +2466,14 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) * 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 --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index f449c045d459..9fa396876854 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -56,7 +56,13 @@ extern int need_post_dma_flush; #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 --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h index 947743d2c0c0..98be731d8f10 100644 --- a/sys/amd64/include/sigframe.h +++ b/sys/amd64/include/sigframe.h @@ -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. @@ -70,6 +71,23 @@ struct osigframe { 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 --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h index 9fcca63f1aab..29a97767cc69 100644 --- a/sys/amd64/include/signal.h +++ b/sys/amd64/include/signal.h @@ -60,7 +60,7 @@ typedef int sig_atomic_t; /* * 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 @@ typedef int sig_atomic_t; * 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 --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h index d02959c232d3..af9b4fd3e732 100644 --- a/sys/amd64/include/ucontext.h +++ b/sys/amd64/include/ucontext.h @@ -73,6 +73,34 @@ typedef struct __mcontext { } 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 --git a/sys/conf/options b/sys/conf/options index 5c67f4972bc2..4433f1b04624 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -77,6 +77,7 @@ ADAPTIVE_MUTEXES 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 diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index d4aa9e3da060..5a8cf704dd22 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -37,6 +37,7 @@ * $FreeBSD$ */ +#include "opt_compat.h" #include "opt_kstack_pages.h" #include @@ -151,12 +152,20 @@ ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); 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 --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index 5d5b39ed5fd9..8f1d801268b3 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -406,6 +406,22 @@ NON_GPROF_ENTRY(sigcode) 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 @@ osigcode: 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 @@ osigcode: 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 --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 80805a2048c5..ff69b568be79 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -165,6 +165,10 @@ int cold = 1; #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 @@ osendsig(catcher, sig, mask, code) 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 @@ osendsig(catcher, sig, mask, code) } #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 @@ sendsig(catcher, sig, mask, code) 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 @@ sendsig(catcher, sig, mask, code) * * MPSAFE */ +#ifdef COMPAT_43 int osigreturn(td, uap) struct thread *td; @@ -557,7 +689,6 @@ osigreturn(td, uap) struct osigcontext *sigcntxp; } */ *uap; { -#ifdef COMPAT_43 struct osigcontext sc; struct trapframe *regs; struct osigcontext *scp; @@ -662,10 +793,116 @@ osigreturn(td, uap) 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 @@ -2162,7 +2399,7 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) #ifndef DEV_NPX mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; -#else /* DEV_NPX */ +#else union savefpu *addr; /* @@ -2192,9 +2429,8 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) 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 @@ -2204,7 +2440,10 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) 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 || @@ -2227,25 +2466,14 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) * 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 --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index f449c045d459..9fa396876854 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -56,7 +56,13 @@ extern int need_post_dma_flush; #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 --git a/sys/i386/include/sigframe.h b/sys/i386/include/sigframe.h index 947743d2c0c0..98be731d8f10 100644 --- a/sys/i386/include/sigframe.h +++ b/sys/i386/include/sigframe.h @@ -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. @@ -70,6 +71,23 @@ struct osigframe { 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 --git a/sys/i386/include/signal.h b/sys/i386/include/signal.h index 9fcca63f1aab..29a97767cc69 100644 --- a/sys/i386/include/signal.h +++ b/sys/i386/include/signal.h @@ -60,7 +60,7 @@ typedef int sig_atomic_t; /* * 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 @@ typedef int sig_atomic_t; * 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 --git a/sys/i386/include/ucontext.h b/sys/i386/include/ucontext.h index d02959c232d3..af9b4fd3e732 100644 --- a/sys/i386/include/ucontext.h +++ b/sys/i386/include/ucontext.h @@ -73,6 +73,34 @@ typedef struct __mcontext { } 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 --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 454cf4963834..4f739d2faa59 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -950,18 +950,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) #endif } -/* - * 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 @@ -1069,6 +1057,15 @@ sigreturn(struct thread *td, 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 --git a/sys/ia64/include/sigframe.h b/sys/ia64/include/sigframe.h index b0772d75c494..d0e886e9bc90 100644 --- a/sys/ia64/include/sigframe.h +++ b/sys/ia64/include/sigframe.h @@ -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 --git a/sys/ia64/include/signal.h b/sys/ia64/include/signal.h index 1014d2b2128b..1a20e01050da 100644 --- a/sys/ia64/include/signal.h +++ b/sys/ia64/include/signal.h @@ -70,7 +70,6 @@ struct ia64_fpreg { #endif #endif -#ifdef _KERNEL /* * Information pushed on stack when a signal is delivered. @@ -82,12 +81,6 @@ struct ia64_fpreg { * 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 --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index fb28d326493c..601920bb435c 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -131,7 +131,7 @@ struct sysent sysent[] = { { 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 @@ struct sysent sysent[] = { { 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 @@ struct sysent sysent[] = { { 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 --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 0d5000e18263..35036098819d 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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 @@ sig_ffs(sigset_t *set) /* * 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 @@ kern_sigaction(td, sig, act, oact, old) 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 @@ done2: 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 @@ osigaction(td, uap) 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 @@ done2: 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 --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 142e8f2b9156..3215b63b2a9e 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -110,7 +110,7 @@ char *syscallnames[] = { "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 @@ char *syscallnames[] = { "#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 @@ char *syscallnames[] = { "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 --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index a0172b882e7f..482b2a96b20c 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -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 --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 3c44ba975d5a..cec3dd4250b1 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -598,18 +598,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 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) { @@ -656,6 +644,15 @@ sigreturn(struct thread *td, struct sigreturn_args *uap) 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 --git a/sys/powerpc/include/signal.h b/sys/powerpc/include/signal.h index 55b16ddd3539..c290bb9bd74e 100644 --- a/sys/powerpc/include/signal.h +++ b/sys/powerpc/include/signal.h @@ -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 --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c index 3c44ba975d5a..cec3dd4250b1 100644 --- a/sys/powerpc/powerpc/machdep.c +++ b/sys/powerpc/powerpc/machdep.c @@ -598,18 +598,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 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) { @@ -656,6 +644,15 @@ sigreturn(struct thread *td, struct sigreturn_args *uap) 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 --git a/sys/sparc64/include/signal.h b/sys/sparc64/include/signal.h index c27ad575ff7c..2b834ad69af1 100644 --- a/sys/sparc64/include/signal.h +++ b/sys/sparc64/include/signal.h @@ -46,14 +46,6 @@ typedef long sig_atomic_t; #define MINSIGSTKSZ (1024 * 4) #endif -#ifdef _KERNEL -typedef int osigset_t; - -struct osigcontext { - int dummy; -}; -#endif - #if __BSD_VISIBLE struct sigcontext { int _dummy; diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 55ef2a9ade70..820305685b26 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -40,6 +40,7 @@ * $FreeBSD$ */ +#include "opt_compat.h" #include "opt_ddb.h" #include "opt_msgbuf.h" @@ -449,20 +450,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 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; @@ -506,6 +493,15 @@ sigreturn(struct thread *td, struct sigreturn_args *uap) 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 * specified by the arguments. diff --git a/sys/sys/_sigset.h b/sys/sys/_sigset.h index dfb954e5b762..77f2a9acfc97 100644 --- a/sys/sys/_sigset.h +++ b/sys/sys/_sigset.h @@ -56,4 +56,8 @@ typedef struct __sigset { __uint32_t __bits[_SIG_WORDS]; } __sigset_t; +#if defined(_KERNEL) && defined(COMPAT_43) +typedef unsigned int osigset_t; +#endif + #endif /* !_SYS__SIGSET_H_ */ diff --git a/sys/sys/signal.h b/sys/sys/signal.h index edbb46097b28..deae42d69976 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -302,6 +302,14 @@ struct sigvec { #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 --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index d2fbacf95d28..d7d7227e0ab7 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -56,11 +56,12 @@ struct sigacts { 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 @@ struct osigaction { }; 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 --git a/sys/sys/syscall.h b/sys/sys/syscall.h index b1da44913dc1..a72b3179b3ed 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -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 --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 4e6f0ea5d536..51fc2f943e17 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -82,7 +82,6 @@ MIASM = \ socket.o \ connect.o \ getpriority.o \ - osigreturn.o \ bind.o \ setsockopt.o \ listen.o \ @@ -214,9 +213,7 @@ MIASM = \ 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 @@ MIASM = \ __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 --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index aa434c2574ee..25c2f53d4185 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -67,7 +67,7 @@ int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg); 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, @@ -78,4 +78,8 @@ 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 --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 6f1904a8a2a3..683c722d08c4 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -361,9 +361,6 @@ struct getpriority_args { 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 sigprocmask_args { 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 @@ struct extattr_delete_link_args { 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 setpriority(struct thread *, struct setpriority_args *); 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 kldsym(struct thread *, struct kldsym_args *); 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 __mac_set_link(struct thread *, struct __mac_set_link_args *); 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 @@ struct orecv_args { 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 osethostname(struct thread *, struct sethostname_args *); 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 @@ struct freebsd4_sendfile_args { 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 --git a/sys/sys/ucontext.h b/sys/sys/ucontext.h index 194b63a73595..dcce16e1a6fb 100644 --- a/sys/sys/ucontext.h +++ b/sys/sys/ucontext.h @@ -53,6 +53,20 @@ typedef struct __ucontext { 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 -- cgit v1.2.3