From owner-freebsd-bugs@FreeBSD.ORG Thu Mar 6 09:20:01 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C09591065673 for ; Thu, 6 Mar 2008 09:20:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 9D6B18FC17 for ; Thu, 6 Mar 2008 09:20:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m269K1pE068488 for ; Thu, 6 Mar 2008 09:20:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m269K17h068487; Thu, 6 Mar 2008 09:20:01 GMT (envelope-from gnats) Resent-Date: Thu, 6 Mar 2008 09:20:01 GMT Resent-Message-Id: <200803060920.m269K17h068487@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Aurelien Jarno Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 89D44106566C for ; Thu, 6 Mar 2008 09:16:26 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 787118FC19 for ; Thu, 6 Mar 2008 09:16:26 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m269DNUV058567 for ; Thu, 6 Mar 2008 09:13:23 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id m269DNxv058566; Thu, 6 Mar 2008 09:13:23 GMT (envelope-from nobody) Message-Id: <200803060913.m269DNxv058566@www.freebsd.org> Date: Thu, 6 Mar 2008 09:13:23 GMT From: Aurelien Jarno To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/121422: FreeBSD doesn't follow x86/x86-64 ABI wrt direction flag X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Mar 2008 09:20:01 -0000 >Number: 121422 >Category: kern >Synopsis: FreeBSD doesn't follow x86/x86-64 ABI wrt direction flag >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Mar 06 09:20:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Aurelien Jarno >Release: all versions affected >Organization: >Environment: >Description: Since version 4.3, gcc changed its behaviour concerning the x86/x86-64 ABI and the direction flag, that is it now assumes that the direction flag is cleared at the entry of a function and it doesn't clear once more if needed. This causes some problems with the FreeBSD kernel which does not clear the direction flag when entering a signal handler. If the signal handler is using code that need the direction flag cleared (for example bzero() or memset()), the code is incorrectly executed. This has been first reported on the Linux kernel, but *BSD kernels have the same problem. See http://gcc.gnu.org/ml/gcc/2008-03/msg00267.html for more details >How-To-Repeat: Testcase for x86-64 #include #include #include #include void handler(int signal) { uint64_t rflags; asm volatile("pushfq ; popq %0" : "=g" (rflags)); if (rflags & (1 << 10)) printf("DF = 1\n"); else printf("DF = 0\n"); } int main() { signal(SIGUSR1, handler); while(1) { asm volatile("std\r\n"); } return 0; } >Fix: Patch attached Patch attached with submission follows: diff -Nurd sys/amd64/amd64/machdep.c sys/amd64/amd64/machdep.c --- sys/amd64/amd64/machdep.c 2008-01-19 19:15:01.000000000 +0100 +++ sys/amd64/amd64/machdep.c 2008-03-06 01:29:07.000000000 +0100 @@ -357,7 +357,7 @@ regs->tf_rsp = (long)sfp; regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_rflags &= ~PSL_T; + regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); diff -Nurd sys/amd64/ia32/ia32_signal.c sys/amd64/ia32/ia32_signal.c --- sys/amd64/ia32/ia32_signal.c 2006-10-05 03:56:10.000000000 +0200 +++ sys/amd64/ia32/ia32_signal.c 2008-03-06 01:29:07.000000000 +0100 @@ -391,7 +391,7 @@ regs->tf_rsp = (uintptr_t)sfp; regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; - regs->tf_rflags &= ~PSL_T; + regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); @@ -511,7 +511,7 @@ regs->tf_rsp = (uintptr_t)sfp; regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_rflags &= ~PSL_T; + regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); diff -Nurd sys/amd64/linux32/linux32_sysvec.c sys/amd64/linux32/linux32_sysvec.c --- sys/amd64/linux32/linux32_sysvec.c 2007-09-20 15:46:26.000000000 +0200 +++ sys/amd64/linux32/linux32_sysvec.c 2008-03-06 01:29:07.000000000 +0100 @@ -402,7 +402,7 @@ regs->tf_rsp = PTROUT(fp); regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode) + linux_sznonrtsigcode; - regs->tf_rflags &= ~PSL_T; + regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); @@ -524,7 +524,7 @@ */ regs->tf_rsp = PTROUT(fp); regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_rflags &= ~PSL_T; + regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); diff -Nurd sys/i386/i386/machdep.c sys/i386/i386/machdep.c --- sys/i386/i386/machdep.c 2008-01-19 19:15:03.000000000 +0100 +++ sys/i386/i386/machdep.c 2008-03-06 01:29:07.000000000 +0100 @@ -416,7 +416,7 @@ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - szosigcode; - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -537,7 +537,7 @@ regs->tf_esp = (int)sfp; regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode; - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -673,7 +673,7 @@ regs->tf_esp = (int)sfp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; diff -Nurd sys/i386/linux/linux_sysvec.c sys/i386/linux/linux_sysvec.c --- sys/i386/linux/linux_sysvec.c 2007-09-20 15:46:26.000000000 +0200 +++ sys/i386/linux/linux_sysvec.c 2008-03-06 01:29:07.000000000 +0100 @@ -389,7 +389,7 @@ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode) + linux_sznonrtsigcode; - regs->tf_eflags &= ~(PSL_T | PSL_VM); + regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -508,7 +508,7 @@ */ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_eflags &= ~(PSL_T | PSL_VM); + regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; diff -Nurd sys/i386/svr4/svr4_machdep.c sys/i386/svr4/svr4_machdep.c --- sys/i386/svr4/svr4_machdep.c 2005-10-19 16:59:54.000000000 +0200 +++ sys/i386/svr4/svr4_machdep.c 2008-03-06 01:29:07.000000000 +0100 @@ -497,13 +497,13 @@ svr4_szsigcode); tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL); - tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC); + tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC|PSL_D); tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL); #else tf->tf_esp = (int)fp; tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); - tf->tf_eflags &= ~PSL_T; + tf->tf_eflags &= ~(PSL_T | PSL_D); tf->tf_cs = _ucodesel; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; diff -Nurd sys/pc98/pc98/machdep.c sys/pc98/pc98/machdep.c --- sys/pc98/pc98/machdep.c 2008-01-19 19:15:05.000000000 +0100 +++ sys/pc98/pc98/machdep.c 2008-03-06 01:29:07.000000000 +0100 @@ -388,7 +388,7 @@ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - szosigcode; - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -509,7 +509,7 @@ regs->tf_esp = (int)sfp; regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode; - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -645,7 +645,7 @@ regs->tf_esp = (int)sfp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_eflags &= ~PSL_T; + regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; >Release-Note: >Audit-Trail: >Unformatted: