diff options
author | Mark Wielaard <mark@klomp.org> | 2021-03-03 21:40:53 +0100 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2021-03-03 21:44:45 +0100 |
commit | 480b6fa3662ba8ffeee274bf0d37423413c01e55 (patch) | |
tree | 0563dc04e7bfce7946dd4772c3fd637adb69b012 | |
parent | c497478390de6a40a74f9ef567b05e39403c6314 (diff) | |
download | elfutils-480b6fa3662ba8ffeee274bf0d37423413c01e55.tar.gz |
readelf: Sanity check verneed and verdef offsets in handle_symtab.
We are going through vna_next, vn_next and vd_next in a while loop.
Make sure that all offsets are sane. We don't want things to wrap
around so we go in cycles.
https://sourceware.org/bugzilla/show_bug.cgi?id=27501
Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r-- | src/ChangeLog | 5 | ||||
-rw-r--r-- | src/readelf.c | 10 |
2 files changed, 14 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 791015bb..14cd6cac 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2021-03-03 Mark Wielaard <mark@klomp.org> + + * readelf.c (handle_symtab): Sanity check verneed vna_next, + vn_next and verdef vd_next offsets. + 2021-03-02 Timm Bäder <tbaeder@redhat.com> * elfcompress.c (process_file): Remove cleanup() function and diff --git a/src/readelf.c b/src/readelf.c index 715af3b3..b9740455 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -2554,7 +2554,9 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) &vernaux_mem); while (vernaux != NULL && vernaux->vna_other != *versym - && vernaux->vna_next != 0) + && vernaux->vna_next != 0 + && (verneed_data->d_size - vna_offset + >= vernaux->vna_next)) { /* Update the offset. */ vna_offset += vernaux->vna_next; @@ -2571,6 +2573,9 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Found it. */ break; + if (verneed_data->d_size - vn_offset < verneed->vn_next) + break; + vn_offset += verneed->vn_next; verneed = (verneed->vn_next == 0 ? NULL @@ -2606,6 +2611,9 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Found the definition. */ break; + if (verdef_data->d_size - vd_offset < verdef->vd_next) + break; + vd_offset += verdef->vd_next; verdef = (verdef->vd_next == 0 ? NULL |