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

Kostik Belousov kostikbel at gmail.com
Fri Dec 30 09:20:12 UTC 2011


The following reply was made to PR amd64/163710; it has been noted by GNATS.

From: Kostik Belousov <kostikbel at gmail.com>
To: Russell Cattelan <cattelan at digitalelves.com>
Cc: freebsd-gnats-submit at freebsd.org
Subject: Re: amd64/163710: setjump in userboot.so  causes stack corruption
Date: Fri, 30 Dec 2011 10:57:08 +0200

 --DbeKRiHxlYa1cCF3
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Fri, Dec 30, 2011 at 03:16:34AM +0000, Russell Cattelan wrote:
 >=20
 > >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:       =20
 > >Keywords:      =20
 > >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 2=
 0:20:10 CST 2011     cattelan at fbsd9-it:/sys/amd64/compile/KLOAD-CAMDEBUG  a=
 md64
 >=20
 > >Description:
 > For some reason the forth interpreter is built and linked as 32bit even=
 =20
 > on amd64.=20
 The native amd64 boot loader is 32bit. Small trampoline is used to
 switch to long mode before the control is passed to the booted kernel.
 
 >=20
 > The specific problem is that the header files used when compiling 32 are
 > the i386 variant which define the jmp_buf as such
 >=20
 > #define	_JBLEN	11		/* Size of the jmp_buf on x86. */
 >=20
 > typedef	struct _jmp_buf { int _jb[_JBLEN + 1]; } jmp_buf[1];
 >=20
 > which results in a struct of 48 bytes
 >=20
 > unfortunately libstand has a specific version of setjmp that wants to sto=
 re
 > 12 - 8 byte values
 >=20
 > 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)
 >=20
 > What is happening then in the function ficlExecC=20
 > the saveTib was getting corrupted due to the jmpbuf stack variable
 > getting over written.=20
 > This causes bogus values to be places in the saveTib structure=20
 > which eventually results in a fault.
 
 How do you build ? It seems that userboot build uses its own ficl
 build from sys/boot/userboot/ficl.
 
 >=20
 >=20
 > This fix is to compile the forth interpreter as 64 bit when running on am=
 d64
 >=20
 >=20
 >=20
 >=20
 >=20
 > >How-To-Repeat:
 >=20
 > >Fix:
 > commit ad5840c9e38ba05bdcab3c9efea1c73272bbd9b7
 > Author: Russell Cattelan <cattelan at digitalelves.com>
 > Date:   Thu Dec 29 20:50:57 2011 -0600
 >=20
 >     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.
 >=20
 > 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=3D           ${BASE_SRCS} sysdep.c softcore.c
 >  CLEANFILES=3D    softcore.c testmain testmain.o
 >  CFLAGS+=3D       -ffreestanding -g3
 >  .if ${MACHINE_CPUARCH} =3D=3D "i386" || ${MACHINE_CPUARCH} =3D=3D "amd64"
 > -CFLAGS+=3D   -mpreferred-stack-boundary=3D2
 >  CFLAGS+=3D       -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft=
 -float
 >  .endif
 >  .if ${MACHINE_CPUARCH} =3D=3D "powerpc" || ${MACHINE_CPUARCH} =3D=3D "ar=
 m"
 > @@ -38,10 +37,6 @@ SOFTWORDS=3D   softcore.fr jhlocal.fr marker.fr freebs=
 d.fr ficllocal.fr \
 >  # Optional OO extension softwords
 >  #SOFTWORDS+=3D   oo.fr classes.fr
 > =20
 > -.if ${MACHINE_CPUARCH} =3D=3D "amd64"
 > -CFLAGS+=3D   -m32 -march=3Di386 -I.
 > -.endif
 > -
 I assume you never did even the buildworld with the change ?
 
 --DbeKRiHxlYa1cCF3
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.18 (FreeBSD)
 
 iEYEARECAAYFAk79fOQACgkQC3+MBN1Mb4jA1gCghqTNd5abxQBT/Y1eOGWZqgjf
 4S4An2flz+MTNX4KUfdSDBl7rYzQrwUv
 =GUlo
 -----END PGP SIGNATURE-----
 
 --DbeKRiHxlYa1cCF3--


More information about the freebsd-amd64 mailing list