Date: Fri, 30 Dec 2011 03:16:34 GMT From: Russell Cattelan <cattelan@digitalelves.com> To: freebsd-gnats-submit@FreeBSD.org Subject: amd64/163710: setjump in userboot.so causes stack corruption Message-ID: <201112300316.pBU3GYJp010175@red.freebsd.org> Resent-Message-ID: <201112300320.pBU3KBf5027259@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 163710 >Category: amd64 >Synopsis: setjump in userboot.so causes stack corruption >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-amd64 >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Dec 30 03:20:10 UTC 2011 >Closed-Date: >Last-Modified: >Originator: Russell Cattelan >Release: FreeBSD 9.0 >Organization: Digtal Elves Inc >Environment: FreeBSD fbsd9-it 9.0-PRERELEASE FreeBSD 9.0-PRERELEASE #183: Thu Dec 29 20:20:10 CST 2011 cattelan@fbsd9-it:/sys/amd64/compile/KLOAD-CAMDEBUG amd64 >Description: For some reason the forth interpreter is built and linked as 32bit even on amd64. The specific problem is that the header files used when compiling 32 are the i386 variant which define the jmp_buf as such #define _JBLEN 11 /* Size of the jmp_buf on x86. */ typedef struct _jmp_buf { int _jb[_JBLEN + 1]; } jmp_buf[1]; which results in a struct of 48 bytes unfortunately libstand has a specific version of setjmp that wants to store 12 - 8 byte values ENTRY(_setjmp) movq %rdi,%rax movq 0(%rsp),%rdx /* retval */ movq %rdx, 0(%rax) /* 0; retval */ movq %rbx, 8(%rax) /* 1; rbx */ movq %rsp,16(%rax) /* 2; rsp */ movq %rbp,24(%rax) /* 3; rbp */ movq %r12,32(%rax) /* 4; r12 */ movq %r13,40(%rax) /* 5; r13 */ movq %r14,48(%rax) /* 6; r14 */ movq %r15,56(%rax) /* 7; r15 */ fnstcw 64(%rax) /* 8; fpu cw */ stmxcsr 68(%rax) /* and mxcsr */ xorq %rax,%rax ret END(_setjmp) What is happening then in the function ficlExecC the saveTib was getting corrupted due to the jmpbuf stack variable getting over written. This causes bogus values to be places in the saveTib structure which eventually results in a fault. This fix is to compile the forth interpreter as 64 bit when running on amd64 >How-To-Repeat: >Fix: commit ad5840c9e38ba05bdcab3c9efea1c73272bbd9b7 Author: Russell Cattelan <cattelan@digitalelves.com> Date: Thu Dec 29 20:50:57 2011 -0600 Change the build of forth interpreter to 64bit. The main problem is that the jmp_buf structure is half the size it needs to be 12 * 4 vs 12 * 8 The setjump functions was then causing stack corruption since the buffer was not large enough. diff --git a/sys/boot/ficl/Makefile b/sys/boot/ficl/Makefile index 5cf54c8..75f4349 100644 --- a/sys/boot/ficl/Makefile +++ b/sys/boot/ficl/Makefile @@ -8,7 +8,6 @@ SRCS= ${BASE_SRCS} sysdep.c softcore.c CLEANFILES= softcore.c testmain testmain.o CFLAGS+= -ffreestanding -g3 .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -CFLAGS+= -mpreferred-stack-boundary=2 CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float .endif .if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm" @@ -38,10 +37,6 @@ SOFTWORDS= softcore.fr jhlocal.fr marker.fr freebsd.fr ficllocal.fr \ # Optional OO extension softwords #SOFTWORDS+= oo.fr classes.fr -.if ${MACHINE_CPUARCH} == "amd64" -CFLAGS+= -m32 -march=i386 -I. -.endif - .if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -m32 -mcpu=powerpc -I. .endif @@ -59,7 +54,8 @@ ${SRCS:M*.c:R:S/$/.o/g}: machine beforedepend ${OBJS}: machine machine: - ln -sf ${.CURDIR}/../../i386/include machine + rm -f machine + ln -sf ${.CURDIR}/../../${MACHINE_CPUARCH}/include machine CLEANFILES+= machine .endif >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112300316.pBU3GYJp010175>