https://sourceware.org/bugzilla/show_bug.cgi?id=33549
Bug ID: 33549
Summary: objdump --ctf: SEGV due to unchecked ctfa_ctfs offset
validation
Product: binutils
Version: 2.45
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: shiraishi at os dot is.s.u-tokyo.ac.jp
Target Milestone: ---
## Summary
We found a bug where file size verification is not performed, which causes a
segmentation fault (SEGV) due to out-of-bounds memory access when an invalid
size is input.
## Reproduction
Tested Environment
```
OS: Manjaro Linux
arch: x86_64
CC: clang 20.1.8
glibc: 2.41
```
## Reproduction Steps
```
wget https://ftp.gnu.org/gnu/binutils/binutils-2.45.tar.xz
tar -xvf binutils-2.45.tar.xz
cd binutils-2.45
export CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer"
export CXXFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer"
export LDFLAGS="-fsanitize=address"
mkdir build
cd build
../configure --prefix=$PWD/install --disable-nls
make -j$(nproc)
printf
'\xEB\x3E\x62\xD7\xA4\xF2\x47\x8B\x00\x01\x02\x03\x04\x05\x06\x07\x06\x07\x6C\x2D\x2D\x64\x65\x62\x75\x67\x67\x69\x8D\x67\x20\x2C\x2D\x46\x00\x00\x00\x00\x20\x2D'
> mini
./binutils/objdump ./mini --target=binary --ctf=.data
```
## Output
```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==222433==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x55e6ee18837e
bp 0x7ffc7b018db0 sp 0x7ffc7b018b00 T0)
==222433==The signal is caused by a READ memory access.
==222433==Hint: this fault was caused by a dereference of a high value address
(see register values below). Disassemble the provided pc to learn which
register was used.
#0 0x55e6ee18837e in ctf_bfdopen_ctfsect
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/libctf/../../libctf/ctf-open-bfd.c:123:17
#1 0x55e6ee06bbd8 in dump_ctf
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:4919:15
#2 0x55e6ee0697f0 in dump_bfd
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5837:2
#3 0x55e6ee068b87 in display_object_bfd
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5911:7
#4 0x55e6ee068a97 in display_any_bfd
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5990:5
#5 0x55e6ee067aa6 in display_file
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:6011:3
#6 0x55e6ee066a2d in main
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:6438:6
#7 0x7f78c7e466b4 in __libc_start_call_main
/usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#8 0x7f78c7e46768 in __libc_start_main
/usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
#9 0x55e6edf123d4 in _start
(/home/pine/Documents/fuzz/analysis2/analysis2/result_zig/objdump/out_objdump_1/default/objdump+0x1663d4)
(BuildId: 77c0b96fce4c4af073e1b502b33c63b354bcea51)
==222433==Register values:
rax = 0x04000f9318cbc92f rbx = 0x00007ffc7b018b00 rcx = 0x200000000000462d
rdx = 0x000000000000000c
rdi = 0x200000000000462d rsi = 0x000055e6ee5be5c0 rbp = 0x00007ffc7b018db0
rsp = 0x00007ffc7b018b00
r8 = 0x00000000ffffffff r9 = 0x0000000000000000 r10 = 0x0000000000000000
r11 = 0x00007f78c7e60420
r12 = 0x00007ffc7b019528 r13 = 0x0000000000000004 r14 = 0x00007f78c82ab000
r15 = 0x000055e6ee680710
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/home/pine/Documents/fuzz/analysis2/binutils-2.45/build/libctf/../../libctf/ctf-open-bfd.c:123:17
in ctf_bfdopen_ctfsect
```
## Root Cause Analysis
The size of le64toh (arc->ctfa_ctfs) is not validated at
libctf/ctf-archive.c:402
```
struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
+ sizeof (uint64_t));
```
Therefore, when an invalid size is input, an out-of-bounds memory reference
occurs at libctf/ctf-open-bfd.c:121, resulting in a SEGV.
```
if (ctfsect->cts_data == NULL)
{
bfderrstr = N_("CTF section is NULL");
goto err;
}
preamble = ctf_arc_bufpreamble (ctfsect);
if (preamble->ctp_flags & CTF_F_DYNSTR)
{
symhdr = &elf_tdata (abfd)->dynsymtab_hdr;
strtab_name = ".dynstr";
symtab_name = ".dynsym";
```
## Proposed Fix
```
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index 6c4595fc..b5d51a84 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -399,7 +399,13 @@ ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
&& (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
{
struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
- return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
+ size_t offset = le64toh (arc->ctfa_ctfs);
+
+ if((offset + sizeof(uint64_t)) > ctfsect->cts_size)
+ {
+ return NULL;
+ }
+ return (const ctf_preamble_t *) ((char *) arc + offset
+ sizeof (uint64_t));
}
else
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
index 7241de70..def9cf6d 100644
--- a/libctf/ctf-open-bfd.c
+++ b/libctf/ctf-open-bfd.c
@@ -119,6 +119,10 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
goto err;
}
preamble = ctf_arc_bufpreamble (ctfsect);
+ if(preamble == NULL)
+ {
+ goto err;
+ }
if (preamble->ctp_flags & CTF_F_DYNSTR)
{
```
--
You are receiving this mail because:
You are on the CC list for the bug.