summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2010-04-14 11:24:15 -0700
committerRoland McGrath <[email protected]>2010-04-14 11:24:15 -0700
commit957072c18a906a43f0b428997d0c2b0da478213b (patch)
treec1a5ecada39db6f45970732966bafb6eed567378
parent7880556cac554ed966a6fa2e9a76d2a2dc4564fa (diff)
Handle truncated phdrs without crash.
-rw-r--r--libelf/ChangeLog5
-rw-r--r--libelf/elf32_getphdr.c7
-rw-r--r--libelf/elf_begin.c16
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)
{