From 9ceebe690f94f24186280e1b38ed5770bf436686 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 3 Jan 2015 00:27:58 +0100 Subject: libdw: Add missing size check to parse_eh_frame_hdr. 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 --- libdw/ChangeLog | 6 ++++++ libdw/dwarf_getcfi_elf.c | 12 ++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'libdw') diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 005ad3f0..6c8fe0f6 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,9 @@ +2015-01-02 Mark Wielaard + + * 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 * dwarf_getlocation.c (__libdw_intern_expression): Check dbg is not diff --git a/libdw/dwarf_getcfi_elf.c b/libdw/dwarf_getcfi_elf.c index 61ca60de..e58eae67 100644 --- a/libdw/dwarf_getcfi_elf.c +++ b/libdw/dwarf_getcfi_elf.c @@ -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; -- cgit v1.2.1