Gentoo Archives: gentoo-commits

From: Sergei Trofimovich <slyfox@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/pax-utils:master commit in: /
Date: Sat, 24 Feb 2018 10:16:54
Message-Id: 1518984645.e7b8f34f4557d7071a955ccab813ec41aeeb966b.slyfox@gentoo
1 commit: e7b8f34f4557d7071a955ccab813ec41aeeb966b
2 Author: Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
3 AuthorDate: Sun Feb 18 20:10:45 2018 +0000
4 Commit: Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
5 CommitDate: Sun Feb 18 20:10:45 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=e7b8f34f
7
8 scanelf.c: fix TEXTREL parsing for files with non-zero load address
9
10 In bug #566118 scanelf failed to decode TEXTRELs on gcc binaries
11 where program headers have absolute addresses:
12
13 $ dumpelf ia64_bug_gcc/cc1plus
14 /* Dynamic tag #25 'DT_RELA' 0x2099518 */
15 {
16 .d_tag = 0x7 ,
17 .d_un = {
18 .d_val = 0x4000000000104B08 ,
19 .d_ptr = 0x4000000000104B08 ,
20 },
21 },
22 /* Section Header #8 '.rela.dyn' 0x20AA610 */
23 {
24 .sh_type = 4 , /* [SHT_RELA] */
25 .sh_addr = 0x4000000000104B08 ,
26 .sh_offset = 1067784 , /* (bytes) */
27 },
28
29 Before the change scanelf assumed DT_RELA.d_ptr is
30 a relative offset. This is not true in general case
31 but good-enough for DSOs as they have zero load address.
32
33 This change extends the check for executables.
34 To make addresses relative again we find load address
35 of first byte from program header with 'p_offset'.
36
37 /* Program Header #2 0xB0 */
38 {
39 .p_type = 1 , /* [PT_LOAD] */
40 .p_offset = 0 , /* (bytes into file) */
41 .p_vaddr = 0x4000000000000000 , /* (virtual addr at runtime) */
42 .p_paddr = 0x4000000000000000 , /* (physical addr at runtime) */
43 },
44
45 Bug: https://bugs.gentoo.org/566118
46 Signed-off-by: Sergei Trofimovich <slyfox <AT> gentoo.org>
47
48 scanelf.c | 24 +++++++++++++++++++-----
49 1 file changed, 19 insertions(+), 5 deletions(-)
50
51 diff --git a/scanelf.c b/scanelf.c
52 index a054408..530edfb 100644
53 --- a/scanelf.c
54 +++ b/scanelf.c
55 @@ -579,6 +579,8 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun
56 Elf ## B ## _Rela *rela; \
57 Elf ## B ## _Dyn *dyn, *drel, *drelsz, *drelent, *dpltrel; \
58 uint32_t pltrel; \
59 + Elf ## B ## _Addr load_address = 0; \
60 + Elf ## B ## _Addr file_offset; \
61 \
62 /* Walk all the dynamic tags to find relocation info */ \
63 drel = drelsz = drelent = dpltrel = NULL; \
64 @@ -605,27 +607,40 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun
65 warnf("ELF is missing relocation information"); \
66 break; \
67 } \
68 + phdr = PHDR ## B(elf->phdr); \
69 + /* Lookup load base: byte 0 is mapped at load_address */ \
70 + for (i = 0; i < EGET(ehdr->e_phnum); ++i) { \
71 + /* Only care about loadable segments. */ \
72 + if (EGET(phdr[i].p_type) != PT_LOAD) \
73 + continue; \
74 + /* We search for the first program header to map into memory */ \
75 + if (EGET(phdr[i].p_offset) != 0) \
76 + continue; \
77 + load_address = EGET(phdr[i].p_vaddr); \
78 + } \
79 switch (EGET(dpltrel->d_un.d_val)) { \
80 case DT_REL: \
81 - if (!VALID_RANGE(elf, EGET(drel->d_un.d_val), sizeof (drel->d_un.d_val))) { \
82 + file_offset = EGET(drel->d_un.d_val) - load_address; \
83 + if (!VALID_RANGE(elf, file_offset, sizeof (drel->d_un.d_val))) { \
84 rel = NULL; \
85 rela = NULL; \
86 warn("%s: DT_REL is out of file range", elf->filename); \
87 break; \
88 } \
89 - rel = REL##B(elf->vdata + EGET(drel->d_un.d_val)); \
90 + rel = REL##B(elf->vdata + file_offset); \
91 rela = NULL; \
92 pltrel = DT_REL; \
93 break; \
94 case DT_RELA: \
95 - if (!VALID_RANGE(elf, EGET(drel->d_un.d_val), sizeof (drel->d_un.d_val))) { \
96 + file_offset = EGET(drel->d_un.d_val) - load_address; \
97 + if (!VALID_RANGE(elf, file_offset, sizeof (drel->d_un.d_val))) { \
98 rel = NULL; \
99 rela = NULL; \
100 warn("%s: DT_RELA is out of file range", elf->filename); \
101 break; \
102 } \
103 rel = NULL; \
104 - rela = RELA##B(elf->vdata + EGET(drel->d_un.d_val)); \
105 + rela = RELA##B(elf->vdata + file_offset); \
106 pltrel = DT_RELA; \
107 break; \
108 default: \
109 @@ -639,7 +654,6 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun
110 rmax = EGET(drelsz->d_un.d_val) / EGET(drelent->d_un.d_val); \
111 \
112 /* search the program segments for relocations */ \
113 - phdr = PHDR ## B(elf->phdr); \
114 for (i = 0; i < EGET(ehdr->e_phnum); ++i) { \
115 Elf ## B ## _Addr vaddr = EGET(phdr[i].p_vaddr); \
116 uint ## B ## _t memsz = EGET(phdr[i].p_memsz); \