diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-11-14 09:14:51 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-11-14 09:14:51 +0000 |
commit | d86f93537428e67ef17441d5f7088d69fd086694 (patch) | |
tree | b54380663dc5e84aeb95f7bdea5ae8308e62015b /usr.bin/ctfconv | |
parent | f5e63138c3aab601f63e9f448db18def29f5cc7a (diff) |
Verify that every section header lies within the mapped file.
Pointed out by Mark Johnston, Markj@FreeBSD
Diffstat (limited to 'usr.bin/ctfconv')
-rw-r--r-- | usr.bin/ctfconv/elf.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/usr.bin/ctfconv/elf.c b/usr.bin/ctfconv/elf.c index 0bd026ebe86..ff71223d301 100644 --- a/usr.bin/ctfconv/elf.c +++ b/usr.bin/ctfconv/elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: elf.c,v 1.8 2017/11/06 14:59:27 mpi Exp $ */ +/* $OpenBSD: elf.c,v 1.9 2017/11/14 09:14:50 mpi Exp $ */ /* * Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org> @@ -80,8 +80,15 @@ elf_getshstab(const char *p, size_t filesize, const char **shstab, { Elf_Ehdr *eh = (Elf_Ehdr *)p; Elf_Shdr *sh; + size_t shoff; - sh = (Elf_Shdr *)(p + eh->e_shoff + eh->e_shstrndx * eh->e_shentsize); + shoff = eh->e_shoff + eh->e_shstrndx * eh->e_shentsize; + if (shoff > (filesize - sizeof(*sh))) { + warnx("unexpected string table size"); + return -1; + } + + sh = (Elf_Shdr *)(p + shoff); if (sh->sh_type != SHT_STRTAB) { warnx("unexpected string table type"); return -1; @@ -109,22 +116,28 @@ elf_getsymtab(const char *p, size_t filesize, const char *shstab, { Elf_Ehdr *eh = (Elf_Ehdr *)p; Elf_Shdr *sh, *symsh; - size_t snlen; + size_t snlen, shoff; ssize_t i; snlen = strlen(ELF_SYMTAB); symsh = NULL; for (i = 0; i < eh->e_shnum; i++) { - sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize); + shoff = eh->e_shoff + i * eh->e_shentsize; + if (shoff > (filesize - sizeof(*sh))) + continue; + sh = (Elf_Shdr *)(p + shoff); if (sh->sh_type != SHT_SYMTAB) continue; if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz)) continue; - if ((sh->sh_offset + sh->sh_size) > filesize) + if (sh->sh_offset > filesize) + continue; + + if (sh->sh_size > (filesize - sh->sh_offset)) continue; if (sh->sh_entsize == 0) @@ -144,8 +157,11 @@ elf_getsymtab(const char *p, size_t filesize, const char *shstab, if (symsh == NULL || (symsh->sh_link >= eh->e_shnum)) return -1; - sh = (Elf_Shdr *)(p + eh->e_shoff + symsh->sh_link * eh->e_shentsize); + shoff = eh->e_shoff + symsh->sh_link * eh->e_shentsize; + if (shoff > (filesize - sizeof(*sh))) + return -1; + sh = (Elf_Shdr *)(p + shoff); if ((sh->sh_offset + sh->sh_size) > filesize) return -1; @@ -164,7 +180,7 @@ elf_getsection(char *p, size_t filesize, const char *sname, const char *shstab, Elf_Ehdr *eh = (Elf_Ehdr *)p; Elf_Shdr *sh; char *sdata = NULL; - size_t snlen, ssz = 0; + size_t snlen, shoff, ssz = 0; ssize_t sidx, i; snlen = strlen(sname); @@ -173,15 +189,18 @@ elf_getsection(char *p, size_t filesize, 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) + shoff = eh->e_shoff + i * eh->e_shentsize; + if (shoff > (filesize - sizeof(*sh))) continue; - sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize); - + sh = (Elf_Shdr *)(p + shoff); if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz)) continue; - if ((sh->sh_offset + sh->sh_size) > filesize) + if (sh->sh_offset > filesize) + continue; + + if (sh->sh_size > (filesize - sh->sh_offset)) continue; if (strncmp(shstab + sh->sh_name, sname, snlen) == 0) { @@ -250,7 +269,7 @@ elf_reloc_apply(const char *p, size_t filesize, const char *shstab, const Elf_Sym *symtab, *sym; ssize_t symtabidx; size_t nsymb, rsym, rtyp, roff; - size_t i, j; + size_t shoff, i, j; uint64_t value; int rsize; @@ -264,18 +283,21 @@ elf_reloc_apply(const char *p, size_t filesize, const char *shstab, /* Apply possible relocation. */ for (i = 0; i < eh->e_shnum; i++) { - if ((eh->e_shoff + i * eh->e_shentsize) > filesize) + shoff = eh->e_shoff + i * eh->e_shentsize; + if (shoff > (filesize - sizeof(*sh))) continue; - sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize); - + sh = (Elf_Shdr *)(p + shoff); if (sh->sh_size == 0) continue; if ((sh->sh_info != sidx) || (sh->sh_link != symtabidx)) continue; - if ((sh->sh_offset + sh->sh_size) > filesize) + if (sh->sh_offset > filesize) + continue; + + if (sh->sh_size > (filesize - sh->sh_offset)) continue; switch (sh->sh_type) { |