summaryrefslogtreecommitdiff
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-01-03 00:27:58 +0100
committerMark Wielaard <mjw@redhat.com>2015-01-15 14:14:21 +0100
commit9ceebe690f94f24186280e1b38ed5770bf436686 (patch)
treeb0b4c6c8d5141e2870c6b9413a08d94e318f5e8d /libdw
parent5316e412a4931d99ac5611e5f89ef187d4e9e335 (diff)
downloadelfutils-9ceebe690f94f24186280e1b38ed5770bf436686.tar.gz
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 <mjw@redhat.com>
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog6
-rw-r--r--libdw/dwarf_getcfi_elf.c12
2 files changed, 10 insertions, 8 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 005ad3f0..6c8fe0f6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -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.
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;