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.
This commit is contained in:
Marcel Moolenaar 2000-11-23 08:55:30 +00:00
parent e26cc4467b
commit cc6ca9b35c
6 changed files with 72 additions and 77 deletions

View File

@ -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;

View File

@ -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

View File

@ -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)];

View File

@ -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

View File

@ -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"

View File

@ -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;