summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-11-14 09:14:51 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-11-14 09:14:51 +0000
commitd86f93537428e67ef17441d5f7088d69fd086694 (patch)
treeb54380663dc5e84aeb95f7bdea5ae8308e62015b /usr.bin
parentf5e63138c3aab601f63e9f448db18def29f5cc7a (diff)
Verify that every section header lies within the mapped file.
Pointed out by Mark Johnston, Markj@FreeBSD
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ctfconv/elf.c54
-rw-r--r--usr.bin/ctfdump/elf.c54
2 files changed, 76 insertions, 32 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) {
diff --git a/usr.bin/ctfdump/elf.c b/usr.bin/ctfdump/elf.c
index 2236a68ac2f..32d846b621b 100644
--- a/usr.bin/ctfdump/elf.c
+++ b/usr.bin/ctfdump/elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elf.c,v 1.7 2017/11/06 14:59:27 mpi Exp $ */
+/* $OpenBSD: elf.c,v 1.8 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) {