summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2021-03-03 21:40:53 +0100
committerMark Wielaard <mark@klomp.org>2021-03-03 21:44:45 +0100
commit480b6fa3662ba8ffeee274bf0d37423413c01e55 (patch)
tree0563dc04e7bfce7946dd4772c3fd637adb69b012
parentc497478390de6a40a74f9ef567b05e39403c6314 (diff)
downloadelfutils-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/ChangeLog5
-rw-r--r--src/readelf.c10
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