aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/linux32/linux32_sysvec.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2018-04-12 20:43:39 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2018-04-12 20:43:39 +0000
commit7c5d1690e98ef7f138f68ff754c141bce0e07024 (patch)
treeb49e74ee83e4dc3782c11d28130f363f2850ac68 /sys/amd64/linux32/linux32_sysvec.c
parent711c77093c0e0af994b04500fd4c4636987df42d (diff)
downloadsrc-7c5d1690e98ef7f138f68ff754c141bce0e07024.tar.gz
src-7c5d1690e98ef7f138f68ff754c141bce0e07024.zip
Fix PSL_T inheritance on exec for x86.
The miscellaneous x86 sysent->sv_setregs() implementations tried to migrate PSL_T from the previous program to the new executed one, but they evaluated regs->tf_eflags after the whole regs structure was bzeroed. Make this functional by saving PSL_T value before zeroing. Note that if the debugger is not attached, executing the first instruction in the new program with PSL_T set results in SIGTRAP, and since all intercepted signals are reset to default dispostion on exec(2), this means that non-debugged process gets killed immediately if PSL_T is inherited. In particular, since suid images drop P_TRACED, attempt to set PSL_T for execution of such program would kill the process. Another issue with userspace PSL_T handling is that it is reset by trap(). It is reasonable to clear PSL_T when entering SIGTRAP handler, to allow the signal to be handled without recursion or delivery of blocked fault. But it is not reasonable to return back to the normal flow with PSL_T cleared. This is too late to change, I think. Discussed with: bde, Ali Mashtizadeh Sponsored by: The FreeBSD Foundation MFC after: 3 weeks Differential revision: https://reviews.freebsd.org/D14995
Notes
Notes: svn path=/head/; revision=332454
Diffstat (limited to 'sys/amd64/linux32/linux32_sysvec.c')
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 3bc83a263f1b..4741cf77bc79 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -719,6 +719,10 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
+ register_t saved_rflags;
+
+ regs = td->td_frame;
+ pcb = td->td_pcb;
if (td->td_proc->p_md.md_ldt != NULL)
user_ldt_free(td);
@@ -731,10 +735,11 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
critical_exit();
pcb->pcb_initial_fpucw = __LINUX_NPXCW__;
+ saved_rflags = regs->tf_rflags & PSL_T;
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = imgp->entry_addr;
regs->tf_rsp = stack;
- regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
+ regs->tf_rflags = PSL_USER | saved_rflags;
regs->tf_gs = _ugssel;
regs->tf_fs = _ufssel;
regs->tf_es = _udatasel;