Bug 29887 - Out of bound read when accessing `file_table` at `case DST__K_SRC_SETFILE` handler in function `parse_module`
Summary: Out of bound read when accessing `file_table` at `case DST__K_SRC_SETFILE` ha...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.40
: P2 normal
Target Milestone: 2.40
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-12-12 03:41 UTC by 2019
Modified: 2022-12-12 09:06 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed: 2022-12-12 00:00:00


Attachments
PoC (20.26 KB, model/x.stl-binary)
2022-12-12 03:41 UTC, 2019
Details

Note You need to log in before you can comment on or make changes to this bug.
Description 2019 2022-12-12 03:41:42 UTC
Created attachment 14508 [details]
PoC

# Reproduce

```bash
cd binutils-gdb
git reset --hard f2f58a399cf3f946983398cdfe52d0eaa72bf877
mkdir build && cd build
../configure --disable-gdb --disable-gdbserver --disable-gdbsupport --disable-libdecnumber --disable-readline --disable-sim --disable-libbacktrace --disable-gas --disable-ld --disable-werror --enable-targets=all CPPFLAGS=-DDEBUG CFLAGS="-g -O0 -fsanitize=address"
make all-binutils MAKEINFO=true && true
binutils/addr2line -e poc.bin 0
```

# Output

```
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 119
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 212
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 44
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 116
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 68
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 176
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 137
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 248
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 177
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 64
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 219
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 48
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 26
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 188
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 243
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 60
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 18
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 70
binutils/addr2line: unknown source command 0
binutils/addr2line: unknown source command 8
=================================================================
==174360==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61100003e388 at pc 0x564c5ffffb6f bp 0x7fff1ab016b0 sp 0x7fff1ab016a0
READ of size 4 at 0x61100003e388 thread T0
    #0 0x564c5ffffb6e in parse_module ../../bfd/vms-alpha.c:4521
    #1 0x564c60000fad in module_find_nearest_line ../../bfd/vms-alpha.c:4902
    #2 0x564c60001911 in _bfd_vms_find_nearest_line ../../bfd/vms-alpha.c:4982
    #3 0x564c5fa2db1e in find_address_in_section ../../binutils/addr2line.c:197
    #4 0x564c5fa48f43 in bfd_map_over_sections ../../bfd/section.c:1366
    #5 0x564c5fa2e8eb in translate_addresses ../../binutils/addr2line.c:337
    #6 0x564c5fa2efbc in process_file ../../binutils/addr2line.c:470
    #7 0x564c5fa2f5b1 in main ../../binutils/addr2line.c:579
    #8 0x7fa61c10ad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0x7fa61c10ae3f in __libc_start_main_impl ../csu/libc-start.c:392
    #10 0x564c5fa2d244 in _start (/binutils-gdb/build/binutils/addr2line+0x343244)

Address 0x61100003e388 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow ../../bfd/vms-alpha.c:4521 in parse_module
Shadow bytes around the buggy address:
  0x0c227ffffc20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c227ffffc70: fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffc90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffca0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffcb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227ffffcc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==174360==ABORTING
Aborted (core dumped)
```

# Analysis

Variable `data` is obtained from `src_ptr + DST_S_W_SRC_UNSWORD`[1], which can be controlled by file content, and then this variable is used to access `file_table`[2] without any check, so out-of-bound read is triggered.

[1] https://github.com/bminor/binutils-gdb/blob/85f9067d3a47d51a46ba369c60fdec752da0f885/bfd/vms-alpha.c#L4519
[2] https://github.com/bminor/binutils-gdb/blob/85f9067d3a47d51a46ba369c60fdec752da0f885/bfd/vms-alpha.c#L4521
Comment 1 Sourceware Commits 2022-12-12 08:59:48 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=77c225bdeb410cf60da804879ad41622f5f1aa44

commit 77c225bdeb410cf60da804879ad41622f5f1aa44
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Dec 12 18:28:49 2022 +1030

    Lack of bounds checking in vms-alpha.c parse_module
    
            PR 29873
            PR 29874
            PR 29875
            PR 29876
            PR 29877
            PR 29878
            PR 29879
            PR 29880
            PR 29881
            PR 29882
            PR 29883
            PR 29884
            PR 29885
            PR 29886
            PR 29887
            PR 29888
            PR 29889
            PR 29890
            PR 29891
            * vms-alpha.c (parse_module): Make length param bfd_size_type.
            Delete length == -1 checks.  Sanity check record_length.
            Sanity check DST__K_MODBEG, DST__K_RTNBEG, DST__K_RTNEND lengths.
            Sanity check DST__K_SOURCE and DST__K_LINE_NUM elements
            before accessing.
            (build_module_list): Pass dst_section size to parse_module.
Comment 2 Alan Modra 2022-12-12 09:06:02 UTC
.