From cde8d159637481ca81846c9518f53cd29dc16c16 Mon Sep 17 00:00:00 2001 From: marcel Date: Thu, 23 Nov 2000 08:55:30 +0000 Subject: [PATCH] o Change the argument of linux_sigreturn to be a pointer to a struct sigframe. We need more than only the signal context. o Properly convert the signal mask when setting up the signal frame in linux_sendsig and properly convert it back in linux_sigreturn. Do some cleanups and improve style while here. --- sys/i386/linux/linux.h | 19 +++--- sys/i386/linux/linux_locore.s | 10 +-- sys/i386/linux/linux_proto.h | 4 +- sys/i386/linux/linux_syscall.h | 2 +- sys/i386/linux/linux_sysent.c | 2 +- sys/i386/linux/linux_sysvec.c | 112 ++++++++++++++++----------------- 6 files changed, 72 insertions(+), 77 deletions(-) diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index 6d3e5a8b928d..d253897cd941 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -335,23 +335,22 @@ struct linux_fpstate { * It is appended to the frame to not interfere with the rest of it. */ struct linux_sigframe { - int sf_sig; - struct linux_sigcontext sf_sc; - struct linux_fpstate fpstate; - u_int extramask[LINUX_NSIG_WORDS-1]; - linux_handler_t sf_handler; + int sf_sig; + struct linux_sigcontext sf_sc; + struct linux_fpstate sf_fpstate; + u_int sf_extramask[LINUX_NSIG_WORDS-1]; + linux_handler_t sf_handler; }; struct linux_rt_sigframe { int sf_sig; - linux_siginfo_t *sf_siginfo;; - struct linux_ucontext *sf_ucontext; - linux_siginfo_t sf_si; - struct linux_ucontext sf_sc; + linux_siginfo_t *sf_siginfo; + struct linux_ucontext *sf_ucontext; + linux_siginfo_t sf_si; + struct linux_ucontext sf_sc; linux_handler_t sf_handler; }; - extern int bsd_to_linux_signal[]; extern int linux_to_bsd_signal[]; extern struct sysentvec linux_sysvec; diff --git a/sys/i386/linux/linux_locore.s b/sys/i386/linux/linux_locore.s index 074021e6748c..f3d93f4de4c9 100644 --- a/sys/i386/linux/linux_locore.s +++ b/sys/i386/linux/linux_locore.s @@ -9,23 +9,23 @@ NON_GPROF_ENTRY(linux_sigcode) call *LINUX_SIGF_HANDLER(%esp) leal LINUX_SIGF_SC(%esp),%ebx /* linux scp */ movl LINUX_SC_GS(%ebx),%gs + movl %esp, %ebx /* pass sigframe */ push %eax /* fake ret addr */ movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */ int $0x80 /* enter kernel with args */ 0: jmp 0b ALIGN_TEXT /* XXXXX */ - _linux_rt_sigcode: call *LINUX_RT_SIGF_HANDLER(%esp) leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */ movl LINUX_SC_GS(%ebx),%gs push %eax /* fake ret addr */ - movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */ + movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */ int $0x80 /* enter kernel with args */ 0: jmp 0b ALIGN_TEXT -/* XXXXX */ +/* XXXXX */ _linux_esigcode: .data @@ -34,7 +34,3 @@ _linux_szsigcode: .long _linux_esigcode-_linux_sigcode _linux_sznonrtsigcode: .long _linux_rt_sigcode-_linux_sigcode - .text - - - diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h index 6540a5235a40..2a61ac543f30 100644 --- a/sys/i386/linux/linux_proto.h +++ b/sys/i386/linux/linux_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.36 2000/11/09 07:27:55 marcel Exp + * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.38 2000/11/23 08:53:19 marcel Exp */ #ifndef _LINUX_SYSPROTO_H_ @@ -322,7 +322,7 @@ struct linux_ipc_args { caddr_t ptr; char ptr_[PAD_(caddr_t)]; }; struct linux_sigreturn_args { - struct linux_sigcontext * scp; char scp_[PAD_(struct linux_sigcontext *)]; + struct linux_sigframe * sfp; char sfp_[PAD_(struct linux_sigframe *)]; }; struct linux_clone_args { int flags; char flags_[PAD_(int)]; diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h index 4d99a07d1eba..645438cacd83 100644 --- a/sys/i386/linux/linux_syscall.h +++ b/sys/i386/linux/linux_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.36 2000/11/09 07:27:55 marcel Exp + * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.38 2000/11/23 08:53:19 marcel Exp */ #define LINUX_SYS_linux_setup 0 diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c index 29c86267534d..c0dbc7298dc2 100644 --- a/sys/i386/linux/linux_sysent.c +++ b/sys/i386/linux/linux_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.36 2000/11/09 07:27:55 marcel Exp + * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.38 2000/11/23 08:53:19 marcel Exp */ #include "opt_compat.h" diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index e836d02bcffb..992529270255 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -202,7 +202,6 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) register struct proc *p = curproc; register struct trapframe *regs; struct linux_rt_sigframe *fp, frame; - struct sigacts *psp = p->p_sigacts; int oonstack; regs = p->p_md.md_regs; @@ -216,7 +215,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { + SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { fp = (struct linux_rt_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct linux_rt_sigframe)); p->p_sigstk.ss_flags |= SS_ONSTACK; @@ -257,17 +256,28 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame.sf_handler = catcher; frame.sf_sig = sig; - frame.sf_siginfo = &fp->sf_si; frame.sf_ucontext = &fp->sf_sc; + /* Fill siginfo structure. */ frame.sf_si.lsi_signo = sig; frame.sf_si.lsi_code = code; frame.sf_si.lsi_addr = (void *)regs->tf_err; + /* * Build the signal context to be used by sigreturn. */ - frame.sf_sc.uc_mcontext.sc_mask = mask->__bits[0]; + frame.sf_sc.uc_flags = 0; /* XXX ??? */ + frame.sf_sc.uc_link = NULL; /* XXX ??? */ + + frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp; + frame.sf_sc.uc_stack.ss_flags = + bsd_to_linux_sigaltstack(p->p_sigstk.ss_flags); + frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size; + + bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); + + frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__bits[0]; frame.sf_sc.uc_mcontext.sc_gs = rgs(); frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; @@ -287,21 +297,11 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; frame.sf_sc.uc_mcontext.sc_trapno = code; /* XXX ???? */ - /* - * Build the remainder of the ucontext struct to be used by sigreturn. - */ - frame.sf_sc.uc_flags = 0; /* XXX ??? */ - frame.sf_sc.uc_link = NULL; /* XXX ??? */ - frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp; - frame.sf_sc.uc_stack.ss_flags = - bsd_to_linux_sigaltstack(p->p_sigstk.ss_flags); - frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size; #ifdef DEBUG printf("Linux-emul(%ld): rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n", (long)p->p_pid, frame.sf_sc.uc_stack.ss_flags, p->p_sigstk.ss_sp, p->p_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); #endif - bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); if (copyout(&frame, fp, sizeof(frame)) != 0) { /* @@ -345,9 +345,15 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) register struct proc *p = curproc; register struct trapframe *regs; struct linux_sigframe *fp, frame; - struct sigacts *psp = p->p_sigacts; + linux_sigset_t lmask; int oonstack, i; + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + /* Signal handler installed with SA_SIGINFO. */ + linux_rt_sendsig(catcher, sig, mask, code); + return; + } + regs = p->p_md.md_regs; oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; @@ -356,17 +362,11 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) (long)p->p_pid, catcher, sig, (void*)mask, code); #endif - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { - /* Signal handler installed with SA_SIGINFO. */ - linux_rt_sendsig(catcher, sig, mask, code); - return; - } - /* * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { + SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { fp = (struct linux_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct linux_sigframe)); p->p_sigstk.ss_flags |= SS_ONSTACK; @@ -404,10 +404,12 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame.sf_handler = catcher; frame.sf_sig = sig; + bsd_to_linux_sigset(mask, &lmask); + /* * Build the signal context to be used by sigreturn. */ - frame.sf_sc.sc_mask = mask->__bits[0]; + frame.sf_sc.sc_mask = lmask.__bits[0]; frame.sf_sc.sc_gs = rgs(); frame.sf_sc.sc_fs = regs->tf_fs; frame.sf_sc.sc_es = regs->tf_es; @@ -426,10 +428,12 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame.sf_sc.sc_ss = regs->tf_ss; frame.sf_sc.sc_err = regs->tf_err; frame.sf_sc.sc_trapno = code; /* XXX ???? */ - bzero(&frame.fpstate, sizeof(struct linux_fpstate)); + + bzero(&frame.sf_fpstate, sizeof(struct linux_fpstate)); + for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) - frame.extramask[i] = mask->__bits[i+1]; - + frame.sf_extramask[i] = lmask.__bits[i+1]; + if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal @@ -468,10 +472,9 @@ linux_sigreturn(p, args) struct proc *p; struct linux_sigreturn_args *args; { - struct linux_sigcontext context; + struct linux_sigframe frame; register struct trapframe *regs; - u_int extramask[LINUX_NSIG_WORDS-1]; - u_int *emp; + linux_sigset_t lmask; int eflags, i; regs = p->p_md.md_regs; @@ -481,18 +484,18 @@ linux_sigreturn(p, args) (long)p->p_pid, (void *)args->scp); #endif /* - * The trampoline code hands us the context. + * The trampoline code hands us the sigframe. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ - if (copyin((caddr_t)args->scp, &context, sizeof(context)) != 0) + if (copyin((caddr_t)args->sfp, &frame, sizeof(frame)) != 0) return (EFAULT); /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) - eflags = context.sc_eflags; + eflags = frame.sf_sc.sc_eflags; /* * XXX do allow users to change the privileged flag PSL_RF. The * cpu sets PSL_RF in tf_eflags for faults. Debuggers should @@ -513,40 +516,37 @@ linux_sigreturn(p, args) * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) - if (!CS_SECURE(context.sc_cs)) { + if (!CS_SECURE(frame.sf_sc.sc_cs)) { trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } p->p_sigstk.ss_flags &= ~SS_ONSTACK; - emp = (u_int *)((caddr_t)args->scp + sizeof(context) + - sizeof(struct linux_fpstate)); - if (copyin((caddr_t)emp, extramask, sizeof(extramask)) == 0) - for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) - p->p_sigmask.__bits[i+1] = extramask[i]; - - SIGSETOLD(p->p_sigmask, context.sc_mask); + lmask.__bits[0] = frame.sf_sc.sc_mask; + for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) + lmask.__bits[i+1] = frame.sf_extramask[i]; + linux_to_bsd_sigset(&lmask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); /* * Restore signal context. */ /* %gs was restored by the trampoline. */ - regs->tf_fs = context.sc_fs; - regs->tf_es = context.sc_es; - regs->tf_ds = context.sc_ds; - regs->tf_edi = context.sc_edi; - regs->tf_esi = context.sc_esi; - regs->tf_ebp = context.sc_ebp; - regs->tf_ebx = context.sc_ebx; - regs->tf_edx = context.sc_edx; - regs->tf_ecx = context.sc_ecx; - regs->tf_eax = context.sc_eax; - regs->tf_eip = context.sc_eip; - regs->tf_cs = context.sc_cs; + regs->tf_fs = frame.sf_sc.sc_fs; + regs->tf_es = frame.sf_sc.sc_es; + regs->tf_ds = frame.sf_sc.sc_ds; + regs->tf_edi = frame.sf_sc.sc_edi; + regs->tf_esi = frame.sf_sc.sc_esi; + regs->tf_ebp = frame.sf_sc.sc_ebp; + regs->tf_ebx = frame.sf_sc.sc_ebx; + regs->tf_edx = frame.sf_sc.sc_edx; + regs->tf_ecx = frame.sf_sc.sc_ecx; + regs->tf_eax = frame.sf_sc.sc_eax; + regs->tf_eip = frame.sf_sc.sc_eip; + regs->tf_cs = frame.sf_sc.sc_cs; regs->tf_eflags = eflags; - regs->tf_esp = context.sc_esp_at_signal; - regs->tf_ss = context.sc_ss; + regs->tf_esp = frame.sf_sc.sc_esp_at_signal; + regs->tf_ss = frame.sf_sc.sc_ss; return (EJUSTRETURN); } @@ -582,7 +582,7 @@ linux_rt_sigreturn(p, args) (long)p->p_pid, (void *)args->ucp); #endif /* - * The trampoline code hands us the u_context. + * The trampoline code hands us the ucontext. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ @@ -626,7 +626,7 @@ linux_rt_sigreturn(p, args) SIG_CANTMASK(p->p_sigmask); /* - * Restore signal context-> + * Restore signal context */ /* %gs was restored by the trampoline. */ regs->tf_fs = context->sc_fs;