diff options
-rw-r--r-- | usr.bin/ctfdump/ctfdump.c | 12 | ||||
-rw-r--r-- | usr.bin/ctfdump/elf.c | 44 |
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; |