File readelf-fix-off-by-one-sanity-check.patch of Package elfutils.13244
From: Joao Moreira <jmoreira@suse.de>
Date: Tue May 28 15:27:22 -03 2019
Subject: [PATCH] readelf: Fix off by one sanity check in handle_gnu_hash
Upstream: https://sourceware.org/ml/elfutils-devel/2017-q1/msg00109.html
Reference: bnc#1033084
We sanity check to make sure we don't index outside the chain array
by testing inner > max_nsyms. But inner is a zero-based index, while
max_nsyms is the maximum number. Change the check to inner >= max_nsyms.
https://sourceware.org/bugzilla/show_bug.cgi?id=21299
Elfutils packaging edits:
- This is a backport from the upstream patch
Signed-off-by: Mark Wielaard <mark@klomp.org>
Signed-off-by: Joao Moreira <jmoreira@suse.de>
--- a/src/readelf.c 2019-05-28 14:17:50.698464582 -0300
+++ b/src/readelf.c 2019-05-28 15:14:36.115079516 -0300
@@ -2911,6 +2911,15 @@
Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+
+ uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
+ if (used_buf > data->d_size)
+ {
+ error (0, 0, gettext ("invalid data in sysv.hash %d: %s"),
+ (int) elf_ndxscn (scn), elf_errmsg(-1));
+ return;
+ }
+
Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
@@ -3004,6 +3013,15 @@
Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
+ uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
+ uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
+ if (used_buf > data->d_size)
+ {
+ error (0, 0, gettext("invalid data in section %d: %s"),
+ (int) elf_ndxscn (scn), elf_errmsg(-1));
+ return;
+ }
+
uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
@@ -3023,6 +3041,13 @@
++nsyms;
if (maxlength < ++lengths[cnt])
++maxlength;
+ if (inner >= max_nsyms)
+ {
+ free(lengths);
+ error (0, 0, gettext("invalid data in section %d: %s"),
+ (int) elf_ndxscn (scn), elf_errmsg(-1));
+ return;
+ }
}
while ((chain[inner++] & 1) == 0);
}