1 |
commit: 18ded0e30ee5a84260cceb80d818b9c21ade4c76 |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Wed Feb 1 20:05:09 2017 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Wed Feb 1 20:05:09 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=18ded0e3 |
7 |
|
8 |
dumpelf: check for invalid program headers |
9 |
|
10 |
URL: https://bugs.gentoo.org/607896 |
11 |
Reported-by: Agostino Sarubbo <ago <AT> gentoo.org> |
12 |
|
13 |
dumpelf.c | 8 ++++---- |
14 |
paxelf.h | 5 +++++ |
15 |
2 files changed, 9 insertions(+), 4 deletions(-) |
16 |
|
17 |
diff --git a/dumpelf.c b/dumpelf.c |
18 |
index 44da3ee..a9c6e05 100644 |
19 |
--- a/dumpelf.c |
20 |
+++ b/dumpelf.c |
21 |
@@ -293,9 +293,6 @@ static void dump_phdr(elfobj *elf, const void *phdr_void, size_t phdr_cnt) |
22 |
Elf ## B ## _Off offset = EGET(phdr->p_offset); \ |
23 |
void *vdata = elf->vdata + offset; \ |
24 |
uint32_t p_type = EGET(phdr->p_type); \ |
25 |
- switch (p_type) { \ |
26 |
- case PT_DYNAMIC: phdr_dynamic_void = phdr_void; break; \ |
27 |
- } \ |
28 |
printf("/* Program Header #%zu 0x%tX */\n{\n", \ |
29 |
phdr_cnt, (uintptr_t)phdr_void - elf->udata); \ |
30 |
printf("\t.p_type = %-10u , /* [%s] */\n", p_type, get_elfptype(p_type)); \ |
31 |
@@ -307,12 +304,15 @@ static void dump_phdr(elfobj *elf, const void *phdr_void, size_t phdr_cnt) |
32 |
printf("\t.p_flags = 0x%-8X , /* %s */\n", (uint32_t)EGET(phdr->p_flags), dump_p_flags(p_type, EGET(phdr->p_flags))); \ |
33 |
printf("\t.p_align = %-10"PRIu64" , /* (min mem alignment in bytes) */\n", EGET(phdr->p_align)); \ |
34 |
\ |
35 |
- if ((off_t)EGET(phdr->p_offset) > elf->len) { \ |
36 |
+ if (!VALID_PHDR(elf, phdr)) { \ |
37 |
printf("\t/* Warning: Program segment is corrupt. */\n"); \ |
38 |
goto done##B; \ |
39 |
} \ |
40 |
\ |
41 |
switch (p_type) { \ |
42 |
+ case PT_DYNAMIC: \ |
43 |
+ phdr_dynamic_void = phdr_void; \ |
44 |
+ break; \ |
45 |
case PT_NOTE: \ |
46 |
dump_notes(elf, B, vdata, vdata + EGET(phdr->p_filesz)); \ |
47 |
break; \ |
48 |
|
49 |
diff --git a/paxelf.h b/paxelf.h |
50 |
index 56fa9f3..90b283c 100644 |
51 |
--- a/paxelf.h |
52 |
+++ b/paxelf.h |
53 |
@@ -45,6 +45,11 @@ typedef struct { |
54 |
EGET(shdr->sh_offset) < (uint64_t)elf->len && \ |
55 |
EGET(shdr->sh_size) < (uint64_t)elf->len && \ |
56 |
EGET(shdr->sh_offset) <= elf->len - EGET(shdr->sh_size)) |
57 |
+#define VALID_PHDR(elf, phdr) \ |
58 |
+ (phdr && \ |
59 |
+ EGET(phdr->p_filesz) < (uint64_t)elf->len && \ |
60 |
+ EGET(phdr->p_offset) < (uint64_t)elf->len && \ |
61 |
+ EGET(phdr->p_filesz) <= elf->len - EGET(phdr->p_offset)) |
62 |
|
63 |
/* prototypes */ |
64 |
extern char *pax_short_hf_flags(unsigned long flags); |