mknod() broken with uclibc built with -O0

Tino Keitel tino.keitel at innominate.com
Thu Dec 11 14:00:48 UTC 2008


On Thu, Dec 11, 2008 at 02:02:07 +0100, Denys Vlasenko wrote:

[...]

> Can you try smaller test program? A-la
> 
> #include <bare_minimum_for_bug_to_happen.h>
> int main() {
> 	mknod("foobar", 0755, makedev(10,63));
> 	return 0;
> }
> 
> If this works, add more stuff until it breaks.
> Tell us what broke it. Show gcc -On -S results.


Here is the test program:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
        mknod("foobar", S_IFCHR|0666, makedev(10,63));
        return 0;
}

$ strace ./test_static
execve("./test_static", ["./test_static"], [/* 18 vars */]) = 0
mknod("foobar", S_IFCHR|0666, makedev(10, 63)) = 0
_exit(0)

So this works as it should. I added a puts("foobar"); after the
mknod(), and this broke:

$ strace ./test_static_stdio_puts 
execve("./test_static_stdio_puts", ["./test_static_stdio_puts"], [/* 18
vars */]) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo
...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo
...}) = 0
mknod("foobar", S_IFCHR|01001000666, makedev(4294965514, 4294967103)) =
0
write(1, "foobar\n"..., 7foobar
)              = 7
_exit(0)                                = ?
$

Another side effect: the device node created with the broken version is
shown correctly in ls inside the buildroot chroot:

crw-r--r--    1 root     root      10,  63 Dec 11 06:55 foobar

The major/minor nummers are shown correctly using the tools of the host
system (outside the chroot):

crw-r--r-- 1 root root 2314, 1048383 Dec 11 14:55 foobar

Here is the assembly of the broken version:

        .file   "test.c"
        .section        .rodata
.LC0:
        .string "foobar"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $4, %esp
        subl    $8, %esp
        pushl   $63
        pushl   $10
        call    gnu_dev_makedev
        addl    $16, %esp
        pushl   %edx
        pushl   %eax
        pushl   $8630
        pushl   $.LC0
        call    mknod
        addl    $16, %esp
        subl    $12, %esp
        pushl   $.LC0
        call    puts
        addl    $16, %esp
        movl    $0, %eax
        movl    -4(%ebp), %ecx
        leave
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .type   gnu_dev_makedev, @function
gnu_dev_makedev:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
        pushl   %ebx
        movl    12(%ebp), %eax
        movzbl  %al,%edx
        movl    8(%ebp), %eax
        andl    $4095, %eax
        sall    $8, %eax
        orl     %edx, %eax
        movl    %eax, %esi
        movl    $0, %edi
        movl    12(%ebp), %ecx
        movl    $0, %ebx
        movl    %ecx, %eax
        movb    $0, %al
        movl    %ebx, %edx
        andl    $0, %edx
        shldl   $12, %eax, %edx
        sall    $12, %eax
        movl    %esi, %ecx
        orl     %eax, %ecx
        movl    %edi, %ebx
        orl     %edx, %ebx
        movl    8(%ebp), %esi
        movl    $0, %edi
        movl    %esi, %eax
        andl    $-4096, %eax
        movl    %edi, %edx
        andl    $0, %edx
        movl    %eax, %esi
        movl    %edx, %edi
        movl    %esi, %edi
        movl    $0, %esi
        movl    %ecx, %eax
        orl     %esi, %eax
        movl    %ebx, %edx
        orl     %edi, %edx
        popl    %ebx
        popl    %esi
        popl    %edi
        leave
        ret
        .size   gnu_dev_makedev, .-gnu_dev_makedev
        .ident  "GCC: (GNU) 4.3.2"
        .section        .note.GNU-stack,"", at progbits

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