diff options
author | Roland McGrath <roland@redhat.com> | 2009-04-14 02:38:19 -0700 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2009-04-14 02:38:19 -0700 |
commit | fa25326f44d65e0b1ee849cbd0da99c2808e1089 (patch) | |
tree | 3e69934d0198e6d0c2ce867df6fe248a24ffc765 | |
parent | 04a14163323bc4d2d335909a2af7259bc53ddf8b (diff) |
Fix RHBZ#494858: fix bad address checks in core file support.
-rw-r--r-- | libdwfl/ChangeLog | 10 | ||||
-rw-r--r-- | libdwfl/core-file.c | 14 | ||||
-rw-r--r-- | libdwfl/dwfl_segment_report_module.c | 21 | ||||
-rw-r--r-- | libdwfl/link_map.c | 1 |
4 files changed, 38 insertions, 8 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index a2487ed0..d2c823fa 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,13 @@ +2009-04-14 Roland McGrath <roland@redhat.com> + + * dwfl_segment_report_module.c: Handle DT_STRTAB value being either + absolute (already adjusted in place) or needing load bias adjustment. + + * core-file.c (dwfl_elf_phdr_memory_callback): Fix return value for + gelf_getphdr failure. Fix file size limit checks. + + * dwfl_segment_report_module.c: Fix underflow in DYNSTRSZ check. + 2009-04-08 Roland McGrath <roland@redhat.com> * dwfl_module_getsym.c: Don't adjust for bias again after diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c index bc881eb9..77f208cc 100644 --- a/libdwfl/core-file.c +++ b/libdwfl/core-file.c @@ -1,5 +1,5 @@ /* Core file handling. - Copyright (C) 2008 Red Hat, Inc. + Copyright (C) 2008, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -278,7 +278,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, do if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL)) - return true; + return false; while (phdr.p_type != PT_LOAD || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr); @@ -320,8 +320,14 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, if (elf->map_address != NULL) (void) more (elf->maximum_size - start); - if (unlikely (end - start > elf->maximum_size)) - end = start + elf->maximum_size; + /* Make sure we don't look past the end of the actual file, + even if the headers tell us to. */ + if (unlikely (end > elf->maximum_size)) + end = elf->maximum_size; + + /* If the file is too small, there is nothing at all to get. */ + if (unlikely (start >= end)) + return false; if (elf->map_address != NULL) { diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index a6639be5..10787bdc 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -519,13 +519,28 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, size_t soname_size = 0; if (dynstrsz != 0 && dynstr_vaddr != 0) { - /* We know the bounds of the .dynstr section. */ - dynstr_vaddr += bias; + /* We know the bounds of the .dynstr section. + + The DYNSTR_VADDR pointer comes from the .dynamic section + (DT_STRTAB, detected above). Ordinarily the dynamic linker + will have adjusted this pointer in place so it's now an + absolute address. But sometimes .dynamic is read-only (in + vDSOs and odd architectures), and sometimes the adjustment + just hasn't happened yet in the memory image we looked at. + So treat DYNSTR_VADDR as an absolute address if it falls + within the module bounds, or try applying the phdr bias + when that adjusts it to fall within the module bounds. */ + + if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end) + && dynstr_vaddr + bias >= module_start + && dynstr_vaddr + bias < module_end) + dynstr_vaddr += bias; + if (unlikely (dynstr_vaddr + dynstrsz > module_end)) dynstrsz = 0; /* Try to get the DT_SONAME string. */ - if (soname_stroff != 0 && soname_stroff < dynstrsz - 1 + if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz && ! read_portion (&soname, &soname_size, dynstr_vaddr + soname_stroff, 0)) name = soname; diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index 30fb445a..2d4d75f1 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -585,7 +585,6 @@ consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0, memory_callback_arg); - if (*elfclass == ELFCLASSNONE) *elfclass = ehdr.e_ident[EI_CLASS]; else if (*elfclass != ehdr.e_ident[EI_CLASS]) |