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:
parent
e26cc4467b
commit
cc6ca9b35c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69081
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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)];
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user