diff options
| author | Mark Wielaard <[email protected]> | 2016-07-06 15:27:56 +0200 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2016-07-11 09:53:29 +0200 |
| commit | 8b5f017ddf1684e225ef59f9243ef411b2556e9c (patch) | |
| tree | b71828472ffda1fe441f2dcf6ac30da9ff769447 /libelf/elf_getphdrnum.c | |
| parent | 96e140f6687922606657a76f185a73cf47908ef2 (diff) | |
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 <[email protected]>
Diffstat (limited to 'libelf/elf_getphdrnum.c')
| -rw-r--r-- | libelf/elf_getphdrnum.c | 58 |
1 files changed, 31 insertions, 27 deletions
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; } |
