https://sourceware.org/bugzilla/show_bug.cgi?id=34401
Bug ID: 34401
Summary: heap-buffer-overflow read in elf_getarsym with
truncated /SYM64/ archive index
Product: elfutils
Version: unspecified
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libelf
Assignee: unassigned at sourceware dot org
Reporter: karankurani3k at gmail dot com
CC: elfutils-devel at sourceware dot org
Target Milestone: ---
Created attachment 16845
--> https://sourceware.org/bugzilla/attachment.cgi?id=16845&action=edit
Standalone reproducer, ASan trace, after-patch trace, and tested diff for
/SYM64/ elf_getarsym OOB read
Reported by:
Karan Kurani <[email protected]>
I found a heap-buffer-overflow read in libelf/elf_getarsym.c when parsing a
malformed 64-bit archive symbol table member named /SYM64/.
Tested version
--------------
Latest elfutils HEAD:
40d077029b3eeff5b4b71b1b0dd0892d0523350c
git status --porcelain printed no output before testing.
Summary
-------
elf_getarsym() does not fully validate that a /SYM64/ archive index member
contains enough bytes for the 8-byte symbol count field plus n 8-byte archive
offset entries.
For /SYM64/, each archive symbol offset entry is 8 bytes.
A malformed archive can contain:
member name: /SYM64/
member size: 9
symbol count: 1
offset-table payload after the count field: 1 byte
The existing validation checks:
n > index_size / w
where w is 8 for /SYM64/.
With index_size=9 and n=1, this check passes because:
1 > 9 / 8
is false.
However, index_size includes the initial 8-byte count field. After reading that
count field, only 1 byte remains, but elf_getarsym() later copies 8 bytes for
the single archive symbol offset entry.
Vulnerable location
-------------------
File:
libelf/elf_getarsym.c
Vulnerable line:
file_data = memcpy (temp_data, elf->map_address + off, sz);
In my ASan build this is reached at:
libelf/elf_getarsym.c:260
Public API path
---------------
The issue is reachable through the public libelf API:
elf_memory()
-> elf_getarsym()
Generated archive layout
------------------------
The generated archive layout is:
ar magic
/SYM64/ member header, size=9
8-byte big-endian symbol count = 1
1 byte of offset-table payload
total archive size = 77 bytes
Runtime proof
-------------
ASan confirms the out-of-bounds read:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 8
#1 elf_getarsym ././elfutils/libelf/elf_getarsym.c:260
0x50700000014d is located 0 bytes after 77-byte region
Impact
------
A malicious or malformed archive file can trigger an out-of-bounds read in
libelf consumers that parse archive symbol tables through elf_getarsym().
The immediate impact is crash/DoS or undefined behavior while processing
attacker-controlled archive files. I am not claiming RCE.
Suggested fix
-------------
Validate that index_size includes both the count word and the complete offset
table before copying n entries.
I tested the following fix:
size_t w = index64_p ? 8 : 4;
...
|| index_size < w
|| n > (index_size - w) / w
After rebuilding libelf and rerunning the same PoC, elf_getarsym() returned a
clean error and no ASan/UBSan issue was reported.
Patch diff tested
-----------------
diff --git a/libelf/elf_getarsym.c b/libelf/elf_getarsym.c
index 79aa3bbe..2ba867ec 100644
--- a/libelf/elf_getarsym.c
+++ b/libelf/elf_getarsym.c
@@ -163,7 +163,7 @@ elf_getarsym (Elf *elf, size_t *ptr)
- int w = index64_p ? 8 : 4;
+ size_t w = index64_p ? 8 : 4;
@@ -188,7 +188,8 @@ elf_getarsym (Elf *elf, size_t *ptr)
- || n > index_size / w)
+ || index_size < w
+ || n > (index_size - w) / w)
Not a duplicate
---------------
This is archive symbol-table parsing in libelf/elf_getarsym.c for /SYM64/.
It is not any of the previously reported DWARF parser issues in .debug_macro,
.debug_str_offsets, .debug_rnglists, .debug_loclists, .debug_frame,
.debug_pubnames, .debug_line, or .debug_addr.
Please include the following credit if this is fixed:
Reported-by: Karan Kurani <[email protected]>
--
You are receiving this mail because:
You are on the CC list for the bug.