summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2015-05-06 18:02:10 +0200
committerMark Wielaard <[email protected]>2015-05-12 16:50:44 +0200
commit281bb49c71665f306b23107cbf821636f59211e0 (patch)
tree200005e78dd12ceeb6f8b2a01591211b42e406f6 /src
parent5e80a1e8f57fbae3bd5687bb80a65e97f824f914 (diff)
elflint: Check gnu_hash has enough data and bitmask_words is not zero.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c31 Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog3
-rw-r--r--src/elflint.c26
2 files changed, 22 insertions, 7 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 089fe93f..e79f457c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,7 +1,8 @@
2015-05-06 Mark Wielaard <[email protected]>
* elflint.c (check_gnu_hash): Return early when 2nd hash function
- shift too big.
+ shift too big. Check there is enough data available. Make sure
+ bitmask_words is not zero.
(check_verdef): Use Elf64_Word for shdr->sh_info cnt.
(check_verneed): Likewise.
(check_attributes): Break when vendor name isn't terminated.
diff --git a/src/elflint.c b/src/elflint.c
index df476a1f..1c6a55a7 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -2091,26 +2091,40 @@ static void
check_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
GElf_Shdr *symshdr)
{
+ if (data->d_size < 4 * sizeof (Elf32_Word))
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': not enough data\n"),
+ idx, section_name (ebl, idx));
+ return;
+ }
+
Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
- if (!powerof2 (bitmask_words))
- ERROR (gettext ("\
-section [%2d] '%s': bitmask size not power of 2: %u\n"),
- idx, section_name (ebl, idx), bitmask_words);
+ if (bitmask_words == 0 || !powerof2 (bitmask_words))
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
+ idx, section_name (ebl, idx), bitmask_words);
+ return;
+ }
size_t bitmask_idxmask = bitmask_words - 1;
if (gelf_getclass (ebl->elf) == ELFCLASS64)
bitmask_words *= 2;
Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
- if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
+ /* Is there still room for the sym chain?
+ Use uint64_t calculation to prevent 32bit overlow. */
+ uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
+ if (used_buf > data->d_size)
{
ERROR (gettext ("\
section [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
idx, section_name (ebl, idx), (long int) shdr->sh_size,
- (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
+ (long int) used_buf);
return;
}