From owner-svn-src-head@freebsd.org Thu Apr 12 20:43:40 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7221AF8F6BF; Thu, 12 Apr 2018 20:43:40 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 2495B6DBC0; Thu, 12 Apr 2018 20:43:40 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 1E9B0105CA; Thu, 12 Apr 2018 20:43:40 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3CKhdr9041950; Thu, 12 Apr 2018 20:43:39 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3CKhdFF041945; Thu, 12 Apr 2018 20:43:39 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201804122043.w3CKhdFF041945@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 12 Apr 2018 20:43:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332454 - in head/sys: amd64/amd64 amd64/ia32 amd64/linux amd64/linux32 i386/i386 X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: in head/sys: amd64/amd64 amd64/ia32 amd64/linux amd64/linux32 i386/i386 X-SVN-Commit-Revision: 332454 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Apr 2018 20:43:40 -0000 Author: kib Date: Thu Apr 12 20:43:39 2018 New Revision: 332454 URL: https://svnweb.freebsd.org/changeset/base/332454 Log: 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 Modified: head/sys/amd64/amd64/machdep.c head/sys/amd64/ia32/ia32_signal.c head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/i386/i386/machdep.c Modified: head/sys/amd64/amd64/machdep.c ============================================================================== --- head/sys/amd64/amd64/machdep.c Thu Apr 12 20:27:57 2018 (r332453) +++ head/sys/amd64/amd64/machdep.c Thu Apr 12 20:43:39 2018 (r332454) @@ -581,9 +581,13 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_ void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct trapframe *regs = td->td_frame; - struct pcb *pcb = td->td_pcb; + struct trapframe *regs; + struct pcb *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); @@ -593,11 +597,12 @@ exec_setregs(struct thread *td, struct image_params *i clear_pcb_flags(pcb, PCB_32BIT); pcb->pcb_initial_fpucw = __INITIAL_FPUCW__; + saved_rflags = regs->tf_rflags & PSL_T; bzero((char *)regs, sizeof(struct trapframe)); regs->tf_rip = imgp->entry_addr; regs->tf_rsp = ((stack - 8) & ~0xFul) + 8; regs->tf_rdi = stack; /* argv */ - regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); + regs->tf_rflags = PSL_USER | saved_rflags; regs->tf_ss = _udatasel; regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; Modified: head/sys/amd64/ia32/ia32_signal.c ============================================================================== --- head/sys/amd64/ia32/ia32_signal.c Thu Apr 12 20:27:57 2018 (r332453) +++ head/sys/amd64/ia32/ia32_signal.c Thu Apr 12 20:43:39 2018 (r332454) @@ -936,9 +936,13 @@ freebsd32_sigreturn(td, uap) void ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct trapframe *regs = td->td_frame; - struct pcb *pcb = td->td_pcb; + struct trapframe *regs; + struct pcb *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); #ifdef COMPAT_43 @@ -949,10 +953,11 @@ ia32_setregs(struct thread *td, struct image_params *i pcb->pcb_gsbase = 0; pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; + 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_ss = _udatasel; regs->tf_cs = _ucode32sel; regs->tf_rbx = imgp->ps_strings; Modified: head/sys/amd64/linux/linux_sysvec.c ============================================================================== --- head/sys/amd64/linux/linux_sysvec.c Thu Apr 12 20:27:57 2018 (r332453) +++ head/sys/amd64/linux/linux_sysvec.c Thu Apr 12 20:43:39 2018 (r332454) @@ -404,9 +404,13 @@ linux_copyout_strings(struct image_params *imgp) static void 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; + struct trapframe *regs; + struct pcb *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); @@ -416,10 +420,11 @@ linux_exec_setregs(struct thread *td, struct image_par pcb->pcb_initial_fpucw = __LINUX_NPXCW__; set_pcb_flags(pcb, PCB_FULL_IRET); + 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_ss = _udatasel; regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; Modified: head/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c Thu Apr 12 20:27:57 2018 (r332453) +++ head/sys/amd64/linux32/linux32_sysvec.c Thu Apr 12 20:43:39 2018 (r332454) @@ -719,7 +719,11 @@ linux_exec_setregs(struct thread *td, struct image_par { 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_par 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; Modified: head/sys/i386/i386/machdep.c ============================================================================== --- head/sys/i386/i386/machdep.c Thu Apr 12 20:27:57 2018 (r332453) +++ head/sys/i386/i386/machdep.c Thu Apr 12 20:43:39 2018 (r332454) @@ -1104,9 +1104,13 @@ sys_sigreturn(td, uap) void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct trapframe *regs = td->td_frame; - struct pcb *pcb = td->td_pcb; + struct trapframe *regs; + struct pcb *pcb; + register_t saved_eflags; + regs = td->td_frame; + pcb = td->td_pcb; + /* Reset pc->pcb_gs and %gs before possibly invalidating it. */ pcb->pcb_gs = _udatasel; load_gs(_udatasel); @@ -1127,10 +1131,11 @@ exec_setregs(struct thread *td, struct image_params *i set_gsbase(td, 0); /* Make sure edx is 0x0 on entry. Linux binaries depend on it. */ + saved_eflags = regs->tf_eflags & PSL_T; bzero((char *)regs, sizeof(struct trapframe)); regs->tf_eip = imgp->entry_addr; regs->tf_esp = stack; - regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); + regs->tf_eflags = PSL_USER | saved_eflags; regs->tf_ss = _udatasel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel;