bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/12613] New: Undetected buffer overflow occurs in ld when supplie


From: nirhasabnis at gmail dot com
Subject: [Bug ld/12613] New: Undetected buffer overflow occurs in ld when supplied with malformed file as a linker script
Date: Mon, 28 Mar 2011 20:38:54 +0000

http://sourceware.org/bugzilla/show_bug.cgi?id=12613

           Summary: Undetected buffer overflow occurs in ld when supplied
                    with malformed file as a linker script
           Product: binutils
           Version: 2.21
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
        AssignedTo: address@hidden
        ReportedBy: address@hidden


Created attachment 5336
  --> http://sourceware.org/bugzilla/attachment.cgi?id=5336
The input file that crashes ld

Overview
========
ld, when supplied with malformed file as a linker script, generates a buffer
overflow. Overflow goes undetected, but it corrupts the stack memory and hence
can lead to a crash in future. Buffer overflow can be confirmed if
D_FORTIFY_SOURCE=2 gcc option is used.

The crash occurs in function lex_warn_invalid in file ldlex.l at line 
sprintf (buf, "\\%03o", (unsigned int) *what);

when *what in hex is greater than 0x7F, the corresponding unsigned integer
value is very large, and hence the octal representation does not fit within 3
bytes of buf, causing the overflow of buf.

E.g. when *what = 0x80; the corresponding unsigned int value is 4294967168,
with corresponding octal value being 37777777600.

Build versions
==============
Binutils version 2.21, 2.20-1 and (may be) prior to 2.20-1. (I have verified
the bug on 2.21, 2.20-1). 
I can see in cvsweb for ld that, the latest version (revision 1.51) of ldlex.l
still has this error.

Steps to Reproduce
===================
To verify the crash
-------------------
1. Compile ld source code with gcc's -D_FORTIFY_SOURCE=2 option.
2. run following command
   ld -T input_file a.out (NOTE: input_file is attached to the report)
3. You should get following output:

./ld:/tmp/input_file:1: ignoring invalid character `\177' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\002' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\003' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
*** buffer overflow detected ***: ./ld terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x50)[0xbf9390]
/lib/tls/i686/cmov/libc.so.6(+0xe12ca)[0xbf82ca]
/lib/tls/i686/cmov/libc.so.6(+0xe0a08)[0xbf7a08]
/lib/tls/i686/cmov/libc.so.6(_IO_default_xsputn+0x9e)[0xb80afe]
/lib/tls/i686/cmov/libc.so.6(_IO_vfprintf+0xe24)[0xb54a34]
/lib/tls/i686/cmov/libc.so.6(__vsprintf_chk+0xad)[0xbf7abd]
/lib/tls/i686/cmov/libc.so.6(__sprintf_chk+0x2d)[0xbf79fd]
./ld[0x804d601]
./ld[0x804e3b2]
./ld[0x804a5bb]
./ld[0x80500e6]
./ld[0x805e302]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb2dbd6]
./ld[0x8049c41]
======= Memory map: ========
001ce000-001e9000 r-xp 00000000 08:21 3629825    /lib/ld-2.11.1.so
001e9000-001ea000 r--p 0001a000 08:21 3629825    /lib/ld-2.11.1.so
001ea000-001eb000 rw-p 0001b000 08:21 3629825    /lib/ld-2.11.1.so
004c0000-004c1000 r-xp 00000000 00:00 0          [vdso]
00556000-00558000 r-xp 00000000 08:21 3654023   
/lib/tls/i686/cmov/libdl-2.11.1.so
00558000-00559000 r--p 00001000 08:21 3654023   
/lib/tls/i686/cmov/libdl-2.11.1.so
00559000-0055a000 rw-p 00002000 08:21 3654023   
/lib/tls/i686/cmov/libdl-2.11.1.so
00b17000-00c6a000 r-xp 00000000 08:21 3654020   
/lib/tls/i686/cmov/libc-2.11.1.so
00c6a000-00c6b000 ---p 00153000 08:21 3654020   
/lib/tls/i686/cmov/libc-2.11.1.so
00c6b000-00c6d000 r--p 00153000 08:21 3654020   
/lib/tls/i686/cmov/libc-2.11.1.so
00c6d000-00c6e000 rw-p 00155000 08:21 3654020   
/lib/tls/i686/cmov/libc-2.11.1.so
00c6e000-00c71000 rw-p 00000000 00:00 0 
00d3f000-00d5c000 r-xp 00000000 08:21 3629139    /lib/libgcc_s.so.1
00d5c000-00d5d000 r--p 0001c000 08:21 3629139    /lib/libgcc_s.so.1
00d5d000-00d5e000 rw-p 0001d000 08:21 3629139    /lib/libgcc_s.so.1
08048000-0811f000 r-xp 00000000 08:21 5457170   
/home/niranjan/test/binutils-2.21/installdir/bin/ld
0811f000-08120000 r--p 000d6000 08:21 5457170   
/home/niranjan/test/binutils-2.21/installdir/bin/ld
08120000-08122000 rw-p 000d7000 08:21 5457170   
/home/niranjan/test/binutils-2.21/installdir/bin/ld
08122000-08126000 rw-p 00000000 00:00 0 
087b9000-087da000 rw-p 00000000 00:00 0          [heap]
b77eb000-b77ed000 rw-p 00000000 00:00 0 
b77fb000-b77fe000 rw-p 00000000 00:00 0 
bfa5a000-bfa6f000 rw-p 00000000 00:00 0          [stack]
Aborted

Verifying the error in conversion
=================================
If the crash cannot be verified, the error in conversion can be verified as
below.

For the command,
ld -T input_file a.out,

the expected output is

$ ld -T input_file a.out
./ld:/tmp/input_file:1: ignoring invalid character `\177' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\002' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\003' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\200' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\211' in expression 
./ld:/tmp/input_file:1: ignoring invalid character `\004' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\010' in expression
./ld:/tmp/input_file:1: syntax error

but actual output is,

$ ld -T input_file a.out
./ld:/tmp/input_file:1: ignoring invalid character `\177' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\002' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\003' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\001' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\000' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\37777777600' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\37777777611' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\004' in expression
./ld:/tmp/input_file:1: ignoring invalid character `\010' in expression
./ld:/tmp/input_file:1: syntax error

Here is the stack trace
=======================
#0  0x0012d422 in __kernel_vsyscall ()
#1  0x0015c651 in *__GI_raise (sig=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x0015fa82 in *__GI_abort () at abort.c:92
#3  0x0019349d in __libc_message (do_abort=2, fmt=0x2660b5 "*** %s ***: %s
terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4  0x00214390 in *__GI___fortify_fail (msg=<value optimized out>) at
fortify_fail.c:32
#5  0x002132ca in *__GI___chk_fail () at chk_fail.c:29
#6  0x00212a08 in _IO_str_chk_overflow (fp=0xbfffdee0, c=55) at
vsprintf_chk.c:35
#7  0x0019bafe in _IO_default_xsputn (f=0xbfffdee0, data=0xbfffde05, n=11) at
genops.c:485
#8  0x0016fa34 in _IO_vfprintf_internal (s=0xbfffdee0, format=0x80e366d
"\\%03o", ap=0xbfffdfc0 "\200\377\377\377/ $") at vfprintf.c:1613
#9  0x00212abd in ___vsprintf_chk (s=0xbfffdfdb "\\377", flags=1, slen=5,
format=0x80e366d "\\%03o", args=0xbfffdfc0 "\200\377\377\377/ $")
    at vsprintf_chk.c:86
#10 0x002129fd in ___sprintf_chk (s=0xbfffdfdb "\\377", flags=1, slen=5,
format=0x80e366d "\\%03o") at sprintf_chk.c:33
#11 0x0804d601 in sprintf (where=0x80e369c " in expression", what=<value
optimized out>) at /usr/include/bits/stdio2.h:34
#12 lex_warn_invalid (where=0x80e369c " in expression", what=<value optimized
out>) at ldlex.l:689
#13 0x0804e3b2 in yylex () at ldlex.l:463
#14 0x0804a5bb in yyparse () at ldgram.c:2473
#15 0x080500e6 in parse_args (argc=4, argv=0xbffff0e4) at lexsup.c:1244
#16 0x0805e302 in main (argc=4, argv=0xbffff0e4) at ./ldmain.c:295 

Details of system on which bug was verified on:
===============================================
Linux kernel: 2.6.32-30-generic 
OS Distribution: Ubuntu-10.04 
Processor type: i686
gcc: version 4.4.3

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]