diff options
author | Mark Wielaard <mjw@redhat.com> | 2016-07-06 15:27:56 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2016-07-11 09:53:29 +0200 |
commit | 8b5f017ddf1684e225ef59f9243ef411b2556e9c (patch) | |
tree | b71828472ffda1fe441f2dcf6ac30da9ff769447 /libelf | |
parent | 96e140f6687922606657a76f185a73cf47908ef2 (diff) | |
download | elfutils-8b5f017ddf1684e225ef59f9243ef411b2556e9c.tar.gz |
libelf: Allow updating phdrs for any e_type.
elf[32|64]_updatenull would sanity check the e_type before allowing to
update the phdrs. This prevents creating an ET_REL file with phdrs. It
also prevents creating any vendor specific ELF file having phdrs. We
only check this when updating/writing out the file. But we would just
read such files. Don't prevent people from creating unexpected ELF files.
elflint will warn for such files.
While writing a new testcase for this another bug was found that
prevented updating a just created phdr because elf_getphdrnum would
sanity check the phdr offset in the file (which doesn't exist yet).
Fix that by only doing such a sanity check if the phdrs haven't been
read in or created yet.
This second bug should have been found by the existing elfshphehdr
test, but that test contained a typo checking elf_getphdrnum.
It tested that the called failed when there were no phdrs, but then
elf_getphdrnum should simply succeed and return zero.
https://bugzilla.redhat.com/show_bug.cgi?id=1352232
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libelf')
-rw-r--r-- | libelf/ChangeLog | 7 | ||||
-rw-r--r-- | libelf/elf32_updatenull.c | 15 | ||||
-rw-r--r-- | libelf/elf_getphdrnum.c | 58 |
3 files changed, 40 insertions, 40 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 82a2a9f4..d445fe6a 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,10 @@ +2016-07-06 Mark Wielaard <mjw@redhat.com> + + * elf32_updatenull.c (updatenull_wrlock): Ignore e_type when + updating phdrs. + * elf_getphdrnum.c (__elf_getphdrnum_chk_rdlock): Only do sanity + checking if phdrs haven't been read in yet. + 2016-06-24 John Ogness <john.ogness@linutronix.de> * elf32_updatenull.c (updatenull_wrlock): Find first section. diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c index 75070628..939aa13e 100644 --- a/libelf/elf32_updatenull.c +++ b/libelf/elf32_updatenull.c @@ -1,5 +1,5 @@ /* Update data structures for changes. - Copyright (C) 2000-2010, 2015 Red Hat, Inc. + Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -140,21 +140,10 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum) off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1); /* Set the program header position. */ - if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL - && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN - || ehdr->e_type == ET_CORE)) + if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf); if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL) { - /* Only executables, shared objects, and core files have a program - header. */ - if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN - && unlikely (ehdr->e_type != ET_CORE)) - { - __libelf_seterrno (ELF_E_INVALID_PHDR); - return -1; - } - size_t phnum; if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0)) return -1; diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c index 061183bb..f91cba98 100644 --- a/libelf/elf_getphdrnum.c +++ b/libelf/elf_getphdrnum.c @@ -1,5 +1,5 @@ /* Return number of program headers in the ELF file. - Copyright (C) 2010, 2014, 2015 Red Hat, Inc. + Copyright (C) 2010, 2014, 2015, 2016 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -84,35 +84,39 @@ __elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst) { int result = __elf_getphdrnum_rdlock (elf, dst); - /* Do some sanity checking to make sure phnum and phoff are consistent. */ - Elf64_Off off = (elf->class == ELFCLASS32 - ? elf->state.elf32.ehdr->e_phoff - : elf->state.elf64.ehdr->e_phoff); - if (unlikely (off == 0)) + /* If the phdrs haven't been created or read in yet then do some + sanity checking to make sure phnum and phoff are consistent. */ + if (elf->state.elf.phdr == NULL) { - *dst = 0; - return result; + Elf64_Off off = (elf->class == ELFCLASS32 + ? elf->state.elf32.ehdr->e_phoff + : elf->state.elf64.ehdr->e_phoff); + if (unlikely (off == 0)) + { + *dst = 0; + return result; + } + + if (unlikely (off >= elf->maximum_size)) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + return -1; + } + + /* Check for too many sections. */ + size_t phdr_size = (elf->class == ELFCLASS32 + ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr)); + if (unlikely (*dst > SIZE_MAX / phdr_size)) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + return -1; + } + + /* Truncated file? Don't return more than can be indexed. */ + if (unlikely (elf->maximum_size - off < *dst * phdr_size)) + *dst = (elf->maximum_size - off) / phdr_size; } - if (unlikely (off >= elf->maximum_size)) - { - __libelf_seterrno (ELF_E_INVALID_DATA); - return -1; - } - - /* Check for too many sections. */ - size_t phdr_size = (elf->class == ELFCLASS32 - ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr)); - if (unlikely (*dst > SIZE_MAX / phdr_size)) - { - __libelf_seterrno (ELF_E_INVALID_DATA); - return -1; - } - - /* Truncated file? Don't return more than can be indexed. */ - if (unlikely (elf->maximum_size - off < *dst * phdr_size)) - *dst = (elf->maximum_size - off) / phdr_size; - return result; } |