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: unassig...@sources.redhat.com ReportedBy: nirhasab...@gmail.com 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. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-binutils