summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/ctfdump/ctfdump.c12
-rw-r--r--usr.bin/ctfdump/elf.c44
2 files changed, 40 insertions, 16 deletions
diff --git a/usr.bin/ctfdump/ctfdump.c b/usr.bin/ctfdump/ctfdump.c
index 6b3e035314b..88c05e1fd1f 100644
--- a/usr.bin/ctfdump/ctfdump.c
+++ b/usr.bin/ctfdump/ctfdump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ctfdump.c,v 1.8 2017/09/23 12:25:39 uwe Exp $ */
+/* $OpenBSD: ctfdump.c,v 1.9 2017/10/05 02:59:39 jsg Exp $ */
/*
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
@@ -66,9 +66,9 @@ const char *elf_idx2sym(size_t *, uint8_t);
/* elf.c */
int iself(const char *, size_t);
int elf_getshstab(const char *, size_t, const char **, size_t *);
-ssize_t elf_getsymtab(const char *, const char *, size_t,
- const Elf_Sym **, size_t *);
-ssize_t elf_getsection(char *, const char *, const char *,
+ssize_t elf_getsymtab(const char *, size_t filesize, const char *,
+ size_t, const Elf_Sym **, size_t *);
+ssize_t elf_getsection(char *, size_t, const char *, const char *,
size_t, const char **, size_t *);
char *decompress(const char *, size_t, off_t);
@@ -201,11 +201,11 @@ elf_dump(char *p, size_t filesize, uint8_t flags)
return 1;
/* Find symbol table location and number of symbols. */
- if (elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb) == -1)
+ if (elf_getsymtab(p, filesize, shstab, shstabsz, &symtab, &nsymb) == -1)
warnx("symbol table not found");
/* Find string table location and size. */
- if (elf_getsection(p, ELF_STRTAB, shstab, shstabsz, &strtab,
+ if (elf_getsection(p, filesize, ELF_STRTAB, shstab, shstabsz, &strtab,
&strtabsz) == -1)
warnx("string table not found");
diff --git a/usr.bin/ctfdump/elf.c b/usr.bin/ctfdump/elf.c
index 3dad0174b3b..04112c45436 100644
--- a/usr.bin/ctfdump/elf.c
+++ b/usr.bin/ctfdump/elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elf.c,v 1.3 2017/08/29 21:10:20 deraadt Exp $ */
+/* $OpenBSD: elf.c,v 1.4 2017/10/05 02:59:39 jsg Exp $ */
/*
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
@@ -26,8 +26,8 @@
#include <string.h>
static int elf_reloc_size(unsigned long);
-static void elf_reloc_apply(const char *, const char *, size_t, ssize_t,
- char *, size_t);
+static void elf_reloc_apply(const char *, size_t, const char *, size_t,
+ ssize_t, char *, size_t);
int
iself(const char *p, size_t filesize)
@@ -103,8 +103,8 @@ elf_getshstab(const char *p, size_t filesize, const char **shstab,
}
ssize_t
-elf_getsymtab(const char *p, const char *shstab, size_t shstabsz,
- const Elf_Sym **symtab, size_t *nsymb)
+elf_getsymtab(const char *p, size_t filesize, const char *shstab,
+ size_t shstabsz, const Elf_Sym **symtab, size_t *nsymb)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
@@ -122,6 +122,12 @@ elf_getsymtab(const char *p, const char *shstab, size_t shstabsz,
if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
continue;
+ if ((sh->sh_offset + sh->sh_size) > filesize)
+ continue;
+
+ if (sh->sh_entsize == 0)
+ continue;
+
if (strncmp(shstab + sh->sh_name, ELF_SYMTAB, snlen) == 0) {
if (symtab != NULL)
*symtab = (Elf_Sym *)(p + sh->sh_offset);
@@ -136,7 +142,7 @@ elf_getsymtab(const char *p, const char *shstab, size_t shstabsz,
}
ssize_t
-elf_getsection(char *p, const char *sname, const char *shstab,
+elf_getsection(char *p, size_t filesize, const char *sname, const char *shstab,
size_t shstabsz, const char **psdata, size_t *pssz)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
@@ -151,16 +157,23 @@ elf_getsection(char *p, const char *sname, const char *shstab,
/* Find the given section. */
for (i = 0; i < eh->e_shnum; i++) {
+ if ((eh->e_shoff + i * eh->e_shentsize) > filesize)
+ continue;
+
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
continue;
+ if ((sh->sh_offset + sh->sh_size) > filesize)
+ continue;
+
if (strncmp(shstab + sh->sh_name, sname, snlen) == 0) {
sidx = i;
sdata = p + sh->sh_offset;
ssz = sh->sh_size;
- elf_reloc_apply(p, shstab, shstabsz, sidx, sdata, ssz);
+ elf_reloc_apply(p, filesize, shstab, shstabsz, sidx,
+ sdata, ssz);
break;
}
}
@@ -211,8 +224,8 @@ do { \
} while (0)
static void
-elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
- ssize_t sidx, char *sdata, size_t ssz)
+elf_reloc_apply(const char *p, size_t filesize, const char *shstab,
+ size_t shstabsz, ssize_t sidx, char *sdata, size_t ssz)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
@@ -226,7 +239,8 @@ elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
int rsize;
/* Find symbol table location and number of symbols. */
- symtabidx = elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb);
+ symtabidx = elf_getsymtab(p, filesize, shstab, shstabsz, &symtab,
+ &nsymb);
if (symtabidx == -1) {
warnx("symbol table not found");
return;
@@ -234,6 +248,9 @@ elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
/* Apply possible relocation. */
for (i = 0; i < eh->e_shnum; i++) {
+ if ((eh->e_shoff + i * eh->e_shentsize) > filesize)
+ continue;
+
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if (sh->sh_size == 0)
@@ -242,6 +259,9 @@ elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
if ((sh->sh_info != sidx) || (sh->sh_link != symtabidx))
continue;
+ if ((sh->sh_offset + sh->sh_size) > filesize)
+ continue;
+
switch (sh->sh_type) {
case SHT_RELA:
rela = (Elf_RelA *)(p + sh->sh_offset);
@@ -251,6 +271,8 @@ elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
roff = rela[j].r_offset;
if (rsym >= nsymb)
continue;
+ if (roff >= filesize)
+ continue;
sym = &symtab[rsym];
value = sym->st_value + rela[j].r_addend;
@@ -269,6 +291,8 @@ elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
roff = rel[j].r_offset;
if (rsym >= nsymb)
continue;
+ if (roff >= filesize)
+ continue;
sym = &symtab[rsym];
value = sym->st_value;