amd64/163710: setjump in userboot.so causes stack corruption

Russell Cattelan cattelan at digitalelves.com
Fri Dec 30 03:20:11 UTC 2011


>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 at 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 at 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:


More information about the freebsd-amd64 mailing list