Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Dec 2007 09:35:51 +0300
From:      "Yuriy Tsibizov" <Yuriy.Tsibizov@gfk.com>
To:        <freebsd-current@freebsd.org>
Subject:   story about lost %ebx (stack corruption in inet_aton ?)
Message-ID:  <78664C02FF341B4FAC63E561846E3BCC0EEA52@ex.hhp.local>

next in thread | raw e-mail | index | archive | help
(this is an update to 'story about lost %ebx (gcc bug?)' mail that seems
to wait for moderato approval)

My first impression was that there is a bug in gcc compiler on 7-BETA
and 8-CURRENT (i386 only, and only if optimization is enabled), but it
seems to be incorrect. Most probably source is stack corruption in
inet_aton()

How to reproduce:
1) Get i386 version of 7-BETA or 8-CURRENT (amd64 does not expose this
bug)
2) make shure you build with default options (empty /etc/make.conf)
3) /sbin/route add 172.17.1.0.0/12 10.0.0.1 (yes, network address is
incorrect)
4) get core dump

core dump shows that in route.c q=3D=3DNULL in last assignment of this =
code
block:
 --------
	q =3D strchr(s,'/');
	if (q && which =3D=3D RTA_DST) {
		*q =3D '\0';
		if ((val =3D inet_network(s)) !=3D INADDR_NONE) {
			inet_makenetandmask(
				val, &su->sin, strtoul(q+1, 0, 0));
			return (0);
		}
		*q =3D '/';
	}
 --------
with relevant asm output:
 --asm--- (-O1)
        movl    $47, 4(%esp)    #,
        movl    12(%ebp), %edx  # s,
        movl    %edx, (%esp)    #,
        call    strchr  #
        movl    %eax, %ebx      #, q.583
## %ebx is q.583

        testl   %eax, %eax      # q.583
        setne   %al     #, tmp160
        cmpl    $1, 8(%ebp)     #, which
        sete    -73(%ebp)       #, D.6325
        testb   %al, -73(%ebp)  # tmp160, D.6325
        je      .L419   #,
        movb    $0, (%ebx)      #,* q.583
        movl    12(%ebp), %eax  # s,
        movl    %eax, (%esp)    #,
        call    __inet_network  #=20
## %ebx here should be =3D=3D 0, because nothing change it below
        movl    %eax, %esi      #, D.6327
        cmpl    $-1, %eax       #, D.6327
        je      .L421   #,
        leal    1(%ebx), %eax   #, D.6328
        movl    $0, 8(%esp)     #,
        movl    $0, 4(%esp)     #,
        movl    %eax, (%esp)    # D.6328,
        call    strtoul #
        movl    %eax, 8(%esp)   # D.6329,
        movl    %edi, 4(%esp)   # su,
        movl    %esi, (%esp)    # D.6327,
        call    inet_makenetandmask     #
        movl    $0, %eax        #, D.6280=20
        jmp     .L385   #
.L421:
## null pointer reference here
        movb    $47, (%ebx)     #,* q.583
.L419: =20
 -- asm---


My findings so far:
for route.c (and 'broken' libc) :
1) code generated by gcc 4.2.1 for this part of route.c is correct for
-O0 and -O1. You can make it with CFLAGS=3D-save-temps -fverbose-asm and
check yourself.
2) if route is built with -O0 it will work well in any case. (will not
use %ebx)
3) if route is built with -O1 -fno-tree-lrs it will work well (it will
not use %ebx to keep q)
4) if -ftree-lrs is enabled with -O1 (or -O2) it will fail (because it
will use %ebx that seems to be =3D=3D 0 after call to inet_network(s)).

for libc:
1) if libc is built with -O0 any optimization on route.c will work well
(it will not push/pop %ebx in __inet_network in libc)
2) if libc is built with -O1 -fno-tree-lrs route will coredump
(-fno-tree-lrs is only a workaround for route.c)
3) -O1 and -O2 libc will give you coredump

I checked inet_network.s asm output and can't find any obvious compiler
errors there.

The only reason for this (as I see now) is a stack corruption in
inet_aton that leads to old %ebx (pushed into stack) being replaced with
0x0 and then popped on return from inet_network.

Yuriy.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?78664C02FF341B4FAC63E561846E3BCC0EEA52>