diff options
| -rw-r--r-- | libelf/ChangeLog | 5 | ||||
| -rw-r--r-- | libelf/elf32_getphdr.c | 7 | ||||
| -rw-r--r-- | libelf/elf_begin.c | 16 |
3 files changed, 18 insertions, 10 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 2ed2761b..7e6b9929 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,8 @@ +2010-04-14 Roland McGrath <[email protected]> + + * elf32_getphdr.c: Check for e_phoff/size outside the file bounds. + * elf_begin.c (file_read_elf): Don't set .phdr here. + 2010-04-13 Roland McGrath <[email protected]> * elf.h: Update from glibc. diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c index 0a617a67..507fc2aa 100644 --- a/libelf/elf32_getphdr.c +++ b/libelf/elf32_getphdr.c @@ -105,6 +105,13 @@ __elfw2(LIBELFBITS,getphdr_wrlock) (elf) size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr)); + if (ehdr->e_phoff < elf->maximum_size + || elf->maximum_size - ehdr->e_phoff < size) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + goto out; + } + if (elf->map_address != NULL) { /* All the data is already mapped. Use it. */ diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 0b9583b2..e46add33 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -326,11 +326,9 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, elf->state.elf32.ehdr = ehdr; elf->state.elf32.shdr = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); - if (ehdr->e_phnum > 0) - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ - elf->state.elf32.phdr - = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); + + /* Don't precache the phdr pointer here. + elf32_getphdr will validate it against the size when asked. */ for (size_t cnt = 0; cnt < scncnt; ++cnt) { @@ -414,11 +412,9 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, elf->state.elf64.ehdr = ehdr; elf->state.elf64.shdr = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff); - if (ehdr->e_phnum > 0) - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ - elf->state.elf64.phdr - = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff); + + /* Don't precache the phdr pointer here. + elf64_getphdr will validate it against the size when asked. */ for (size_t cnt = 0; cnt < scncnt; ++cnt) { |
