libdw: Add missing size check to parse_eh_frame_hdr.
authorMark Wielaard <mjw@redhat.com>
Fri, 2 Jan 2015 23:27:58 +0000 (00:27 +0100)
committerMark Wielaard <mjw@redhat.com>
Thu, 15 Jan 2015 13:14:21 +0000 (14:14 +0100)
afl-fuzz showed that when parse_eh_frame_hdr was called from
getcfi_scn_eh_frame invalid data could be read because of a missing size
check. That check was there when parse_eh_frame_hdr was called from
getcfi_gnu_eh_frame. Move the size check into parse_eh_frame. And add
an extra check to make sure d_buf is not NULL.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
libdw/ChangeLog
libdw/dwarf_getcfi_elf.c

index 005ad3f..6c8fe0f 100644 (file)
@@ -1,5 +1,11 @@
 2015-01-02  Mark Wielaard  <mjw@redhat.com>
 
+       * dwarf_getcfi_elf.c (parse_eh_frame_hdr): Add size check.
+       (getcfi_gnu_eh_frame): Remove size check. Check d_buf is not NULL.
+       (getcfi_scn_eh_frame): Check d_buf is not NULL.
+
+2015-01-02  Mark Wielaard  <mjw@redhat.com>
+
        * dwarf_getlocation.c (__libdw_intern_expression): Check dbg is not
        NULL for DW_OP_call_ref and DW_OP_GNU_implicit_pointer. For
        DW_OP_addr if dbg is NULL then read argument directly.
index 61ca60d..e58eae6 100644 (file)
@@ -76,7 +76,7 @@ parse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr,
 {
   const uint8_t *h = hdr;
 
-  if (*h++ != 1)               /* version */
+  if (hdr_size < 4 || *h++ != 1)               /* version */
     return (void *) -1l;
 
   uint8_t eh_frame_ptr_encoding = *h++;
@@ -125,15 +125,11 @@ parse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr,
 static Dwarf_CFI *
 getcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr)
 {
-  if (unlikely (phdr->p_filesz < 4))
-    goto invalid;
-
   Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz,
                                         ELF_T_BYTE);
-  if (data == NULL)
+  if (data == NULL || data->d_buf == NULL)
     {
     invalid_hdr:
-    invalid:
       /* XXX might be read error or corrupt phdr */
       __libdw_seterrno (DWARF_E_INVALID_CFI);
       return NULL;
@@ -211,7 +207,7 @@ getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr,
                     Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr)
 {
   Elf_Data *data = elf_rawdata (scn, NULL);
-  if (data == NULL)
+  if (data == NULL || data->d_buf == NULL)
     {
       __libdw_seterrno (DWARF_E_INVALID_ELF);
       return NULL;
@@ -223,7 +219,7 @@ getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr,
       if (hdr_scn != NULL)
        {
          Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL);
-         if (hdr_data != NULL)
+         if (hdr_data != NULL && hdr_data->d_buf != NULL)
            {
              GElf_Addr eh_frame_vaddr;
              cfi->search_table_vaddr = hdr_vaddr;