mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
linux(4): Cleanup signal trampolines
This is the first stage of a signal trampolines refactoring. From trampolines retired emulation of the 'call' instruction, which is replaced by direct call of a signal handler. The signal handler address is in the register. The previous trampoline implemenatation used semi-Linux-way to call a signal handler via the 'jmp' instruction. Wherefore the trampoline emulated a 'call' instruction to into the stack the return address for signal handler's 'ret' instruction. Wherefore handmade DWARD annotations was used. While here rephrased and removed excessive comments. MFC after: 2 weeks
This commit is contained in:
parent
0b5d5dc376
commit
ba279bcd6d
12 changed files with 27 additions and 82 deletions
|
|
@ -314,7 +314,6 @@ typedef struct l_siginfo {
|
|||
struct l_rt_sigframe {
|
||||
struct l_ucontext sf_sc;
|
||||
struct l_siginfo sf_si;
|
||||
l_handler_t sf_handler;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ __FBSDID("$FreeBSD$");
|
|||
#include <amd64/linux/linux.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
|
||||
ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
|
||||
ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
|
||||
ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
|
||||
ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
|
||||
|
|
|
|||
|
|
@ -11,23 +11,14 @@
|
|||
linux_platform:
|
||||
.asciz "x86_64"
|
||||
|
||||
|
||||
.text
|
||||
/*
|
||||
* To avoid excess stack frame the signal trampoline code emulates
|
||||
* the 'call' instruction.
|
||||
*/
|
||||
|
||||
ENTRY(linux_rt_sigcode)
|
||||
movq %rsp, %rbx /* preserve sigframe */
|
||||
call .getip
|
||||
.getip:
|
||||
popq %rax
|
||||
add $.startrtsigcode-.getip, %rax /* ret address */
|
||||
pushq %rax
|
||||
jmp *LINUX_RT_SIGF_HANDLER(%rbx)
|
||||
movq %rsp, %rbx /* rt_sigframe for rt_sigreturn */
|
||||
call *%rcx /* call signal handler */
|
||||
.startrtsigcode:
|
||||
movq $LINUX_SYS_linux_rt_sigreturn,%rax /* linux_rt_sigreturn() */
|
||||
syscall /* enter kernel with args */
|
||||
movq $LINUX_SYS_linux_rt_sigreturn, %rax
|
||||
syscall
|
||||
hlt
|
||||
.endrtsigcode:
|
||||
0: jmp 0b
|
||||
|
|
|
|||
|
|
@ -686,10 +686,10 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
regs->tf_rax = 0;
|
||||
regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */
|
||||
regs->tf_rdx = (register_t)&sfp->sf_sc; /* arg 3 in %rdx */
|
||||
regs->tf_rcx = (register_t)catcher;
|
||||
|
||||
/* Fill in POSIX parts. */
|
||||
siginfo_to_lsiginfo(&ksi->ksi_info, &sf.sf_si, sig);
|
||||
sf.sf_handler = catcher;
|
||||
|
||||
mtx_unlock(&psp->ps_mtx);
|
||||
PROC_UNLOCK(p);
|
||||
|
|
|
|||
|
|
@ -429,15 +429,12 @@ struct l_fpstate {
|
|||
/*
|
||||
* We make the stack look like Linux expects it when calling a signal
|
||||
* handler, but use the BSD way of calling the handler and sigreturn().
|
||||
* This means that we need to pass the pointer to the handler too.
|
||||
* It is appended to the frame to not interfere with the rest of it.
|
||||
*/
|
||||
struct l_sigframe {
|
||||
l_int sf_sig;
|
||||
struct l_sigcontext sf_sc;
|
||||
struct l_fpstate sf_fpstate;
|
||||
l_uint sf_extramask[1];
|
||||
l_handler_t sf_handler;
|
||||
};
|
||||
|
||||
struct l_rt_sigframe {
|
||||
|
|
@ -446,7 +443,6 @@ struct l_rt_sigframe {
|
|||
l_uintptr_t sf_ucontext;
|
||||
l_siginfo_t sf_si;
|
||||
struct l_ucontext sf_sc;
|
||||
l_handler_t sf_handler;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <amd64/linux32/linux.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
|
||||
ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
|
||||
ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
|
||||
ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
|
||||
ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
|
||||
ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
|
||||
ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
|
||||
|
|
|
|||
|
|
@ -14,38 +14,22 @@ linux_platform:
|
|||
.text
|
||||
.code32
|
||||
|
||||
/*
|
||||
* To avoid excess stack frame the signal trampoline code emulates
|
||||
* the 'call' instruction.
|
||||
*/
|
||||
ENTRY(__kernel_sigreturn)
|
||||
movl %esp, %ebx /* preserve sigframe */
|
||||
call .getip0
|
||||
.getip0:
|
||||
popl %eax
|
||||
add $.startsigcode-.getip0, %eax /* ret address */
|
||||
push %eax
|
||||
jmp *LINUX_SIGF_HANDLER(%ebx)
|
||||
movl %esp, %ebx /* sigframe for sigreturn */
|
||||
call *%edi /* call signal handler */
|
||||
.startsigcode:
|
||||
popl %eax
|
||||
movl $LINUX32_SYS_linux_sigreturn,%eax /* linux_sigreturn() */
|
||||
int $0x80 /* enter kernel with args */
|
||||
popl %eax /* gcc unwind code need this */
|
||||
movl $LINUX32_SYS_linux_sigreturn, %eax
|
||||
int $0x80
|
||||
.endsigcode:
|
||||
0: jmp 0b
|
||||
|
||||
ENTRY(__kernel_rt_sigreturn)
|
||||
leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */
|
||||
leal LINUX_RT_SIGF_SC(%ebx),%ecx /* linux sigcontext */
|
||||
movl %esp, %edi
|
||||
call .getip1
|
||||
.getip1:
|
||||
popl %eax
|
||||
add $.startrtsigcode-.getip1, %eax /* ret address */
|
||||
push %eax
|
||||
jmp *LINUX_RT_SIGF_HANDLER(%edi)
|
||||
leal LINUX_RT_SIGF_UC(%esp), %ebx /* linux ucontext for rt_sigreturn */
|
||||
call *%edi /* call signal handler */
|
||||
.startrtsigcode:
|
||||
movl $LINUX32_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */
|
||||
int $0x80 /* enter kernel with args */
|
||||
movl $LINUX32_SYS_linux_rt_sigreturn, %eax
|
||||
int $0x80
|
||||
.endrtsigcode:
|
||||
0: jmp 0b
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
|
||||
bzero(&frame, sizeof(frame));
|
||||
|
||||
frame.sf_handler = PTROUT(catcher);
|
||||
frame.sf_sig = sig;
|
||||
frame.sf_siginfo = PTROUT(&fp->sf_si);
|
||||
frame.sf_ucontext = PTROUT(&fp->sf_sc);
|
||||
|
|
@ -367,6 +366,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/* Build context to run handler in. */
|
||||
regs->tf_rsp = PTROUT(fp);
|
||||
regs->tf_rip = __kernel_rt_sigreturn;
|
||||
regs->tf_rdi = PTROUT(catcher);
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
regs->tf_ss = _udatasel;
|
||||
|
|
@ -431,7 +431,6 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
|
||||
bzero(&frame, sizeof(frame));
|
||||
|
||||
frame.sf_handler = PTROUT(catcher);
|
||||
frame.sf_sig = sig;
|
||||
|
||||
bsd_to_linux_sigset(mask, &lmask);
|
||||
|
|
@ -473,6 +472,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/* Build context to run handler in. */
|
||||
regs->tf_rsp = PTROUT(fp);
|
||||
regs->tf_rip = __kernel_sigreturn;
|
||||
regs->tf_rdi = PTROUT(catcher);
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
regs->tf_ss = _udatasel;
|
||||
|
|
|
|||
|
|
@ -404,15 +404,12 @@ struct l_fpstate {
|
|||
/*
|
||||
* We make the stack look like Linux expects it when calling a signal
|
||||
* handler, but use the BSD way of calling the handler and sigreturn().
|
||||
* This means that we need to pass the pointer to the handler too.
|
||||
* It is appended to the frame to not interfere with the rest of it.
|
||||
*/
|
||||
struct l_sigframe {
|
||||
l_int sf_sig;
|
||||
struct l_sigcontext sf_sc;
|
||||
struct l_fpstate sf_fpstate;
|
||||
l_uint sf_extramask[LINUX_NSIG_WORDS-1];
|
||||
l_handler_t sf_handler;
|
||||
};
|
||||
|
||||
struct l_rt_sigframe {
|
||||
|
|
@ -421,7 +418,6 @@ struct l_rt_sigframe {
|
|||
struct l_ucontext *sf_ucontext;
|
||||
l_siginfo_t sf_si;
|
||||
struct l_ucontext sf_sc;
|
||||
l_handler_t sf_handler;
|
||||
};
|
||||
|
||||
extern struct sysentvec linux_sysvec;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@ __FBSDID("$FreeBSD$");
|
|||
#include <i386/linux/linux.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
|
||||
ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
|
||||
ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
|
||||
ASSYM(LINUX_SC_GS, offsetof(struct l_sigcontext, sc_gs));
|
||||
ASSYM(LINUX_SC_EFLAGS, offsetof(struct l_sigcontext, sc_eflags));
|
||||
ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
|
||||
ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
|
||||
ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
|
||||
ASSYM(LINUX_SC_ESP, offsetof(struct l_sigcontext, sc_esp));
|
||||
|
|
|
|||
|
|
@ -15,38 +15,22 @@ linux_platform:
|
|||
|
||||
.text
|
||||
|
||||
/*
|
||||
* To avoid excess stack frame the signal trampoline code emulates
|
||||
* the 'call' instruction.
|
||||
*/
|
||||
ENTRY(__kernel_sigreturn)
|
||||
movl %esp, %ebx /* preserve sigframe */
|
||||
call .getip0
|
||||
.getip0:
|
||||
popl %eax
|
||||
add $.startsigcode-.getip0, %eax /* ret address */
|
||||
push %eax
|
||||
jmp *LINUX_SIGF_HANDLER(%ebx)
|
||||
movl %esp, %ebx /* sigframe for sigreturn */
|
||||
call *%edi /* call signal handler */
|
||||
.startsigcode:
|
||||
popl %eax /* gcc unwind code need this */
|
||||
movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */
|
||||
int $0x80 /* enter kernel with args */
|
||||
movl $LINUX_SYS_linux_sigreturn, %eax
|
||||
int $0x80
|
||||
.endsigcode:
|
||||
0: jmp 0b
|
||||
|
||||
ENTRY(__kernel_rt_sigreturn)
|
||||
leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */
|
||||
leal LINUX_RT_SIGF_SC(%ebx),%ecx /* linux sigcontext */
|
||||
movl %esp, %edi
|
||||
call .getip1
|
||||
.getip1:
|
||||
popl %eax
|
||||
add $.startrtsigcode-.getip1, %eax /* ret address */
|
||||
push %eax
|
||||
jmp *LINUX_RT_SIGF_HANDLER(%edi)
|
||||
leal LINUX_RT_SIGF_UC(%esp), %ebx /* linux ucontext for rt_sigreturn */
|
||||
call *%edi /* call signal handler */
|
||||
.startrtsigcode:
|
||||
movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */
|
||||
int $0x80 /* enter kernel with args */
|
||||
movl $LINUX_SYS_linux_rt_sigreturn, %eax
|
||||
int $0x80
|
||||
.endrtsigcode:
|
||||
0: jmp 0b
|
||||
|
||||
|
|
|
|||
|
|
@ -422,7 +422,6 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
|
||||
bzero(&frame, sizeof(frame));
|
||||
|
||||
frame.sf_handler = catcher;
|
||||
frame.sf_sig = sig;
|
||||
frame.sf_siginfo = &fp->sf_si;
|
||||
frame.sf_ucontext = &fp->sf_sc;
|
||||
|
|
@ -473,6 +472,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/* Build context to run handler in. */
|
||||
regs->tf_esp = (int)fp;
|
||||
regs->tf_eip = __kernel_rt_sigreturn;
|
||||
regs->tf_edi = catcher;
|
||||
regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
regs->tf_ds = _udatasel;
|
||||
|
|
@ -532,7 +532,6 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
|
||||
bzero(&frame, sizeof(frame));
|
||||
|
||||
frame.sf_handler = catcher;
|
||||
frame.sf_sig = sig;
|
||||
|
||||
bsd_to_linux_sigset(mask, &lmask);
|
||||
|
|
@ -574,6 +573,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/* Build context to run handler in. */
|
||||
regs->tf_esp = (int)fp;
|
||||
regs->tf_eip = __kernel_sigreturn;
|
||||
regs->tf_edi = catcher;
|
||||
regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
regs->tf_ds = _udatasel;
|
||||
|
|
|
|||
Loading…
Reference in a new issue