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.

Reply via email to