segfault with static programs that don't use stdio functions

Tino Keitel tino.keitel at innominate.com
Wed Dec 10 14:57:30 UTC 2008


Hi,

as the bug tracker is down, I try it here.

I discovered that all statically linked programs without stdio usage
segfault with uclibc 0.9.29 and later. Here is the example program I
used:

#include <unistd.h>
#include <stdio.h>

int main(void) {
        write(1, "test\n", 5);
#ifdef USE_STDIO
        puts("test2");
#endif
        return 0;
}

I got this segfault with uclibc 0.9.29 and gcc 4.1 first. It happens on
i386, but not on big endian ARM. Here is the procedure how I tracked
this down with buildroot from latest git, using uclibc 0.9.30 and gcc
4.3.2:

This is the behaviour with stdio usage:

$ ./i386_build/staging/usr/bin/i386-linux-uclibc-gcc -o test -Wall -W
-g3 -O0 -static ~/test.c -DUSE_STDIO
$ ./test
test
test2
$

Without stdio usage:

$ ./i386_build/staging/usr/bin/i386-linux-uclibc-gcc -o test -Wall -W
-g3 -O0 -static ~/test.c
Segmentation fault
$

I built uclibc with DODEBUG enabled, and funnily segfault went away,
because it seems to be triggered with -O2 only. I changed the -O0 in
Rules.mak to -O2 to get debugging information and the segfault.

In gdb, I traced the bug to the invocation of _stdio_init():

$ gdb ./test
(gdb) break __uClibc_main.c:232
Breakpoint 1 at 0x8048311: file libc/misc/internals/__uClibc_main.c,
line 232.
(gdb) run
Starting program: /home/tkeitel/src/buildroot/test 

Breakpoint 1, *__GI___uClibc_init () at
libc/misc/internals/__uClibc_main.c:233
233             _stdio_init();
(gdb) print _stdio_init
No symbol "_stdio_init" in current context.
(gdb) step

Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) bt
#0  0x00000000 in ?? ()
#1  0x080483ca in __uClibc_main (main=0x8048188 <main>, argc=1, 
    argv=0xff87dac4, app_init=0x8048094 <_init>, app_fini=0x8048c10
#<_fini>, 
    rtld_fini=0, stack_end=0xff87dabc)
    at libc/misc/internals/__uClibc_main.c:318
#2  0x080480d1 in _start () at libc/sysdeps/linux/i386/crt1.S:128

So, _stdio_init() was called because the NULL check failed for some
reason:

    if (likely(_stdio_init != NULL))
        _stdio_init();

Without the likely(), the segfault also happens.

In uclibc 0.9.29, the weak _stdio_init declaration was extended by
attribute_hidden. I removed this attribute, and the segfault didn't
happen anymore. However, another segfault happend at the invocation of
_stdio_term(), which had the same problem with attribute_hidden.

Regards,
Tino

-- 
Tino Keitel
Software Engineer
 
Innominate Security Technologies AG
/protecting industrial networks/
Tel: +49.30.6392-3309
Fax: +49.30.6392-3307
Albert-Einstein-Str. 14
D-12489 Berlin
http://www.innominate.com/

Register Court: AG Charlottenburg, HRB 81603
Management Board: Dirk Seewald
Chairman of the Supervisory Board: Volker Bibelhausen

INNOMINATE IS MOVING. FROM 17.12.2008 OUR BUSINESS CONTACT DATA WILL BE
CHANGED:

Rudower Chaussee 13, 12489Berlin / Germany
tel: +49.30.921028-0 (head office)
tel: +49.30.921028-206 (personal extension)
fax: +49.30. 921028-020



More information about the uClibc mailing list