Gentoo Archives: gentoo-commits

From: "Mike Frysinger (vapier)" <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-projects commit in pax-utils: scanelf.c
Date: Sat, 28 Feb 2015 22:59:39
Message-Id: 20150228225934.C2FEA12C3C@oystercatcher.gentoo.org
1 vapier 15/02/28 22:59:34
2
3 Modified: scanelf.c
4 Log:
5 scanelf: add more range checks to deal with corrupt elfs
6
7 Revision Changes Path
8 1.277 pax-utils/scanelf.c
9
10 file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?rev=1.277&view=markup
11 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?rev=1.277&content-type=text/plain
12 diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?r1=1.276&r2=1.277
13
14 Index: scanelf.c
15 ===================================================================
16 RCS file: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v
17 retrieving revision 1.276
18 retrieving revision 1.277
19 diff -u -r1.276 -r1.277
20 --- scanelf.c 28 Feb 2015 22:57:40 -0000 1.276
21 +++ scanelf.c 28 Feb 2015 22:59:34 -0000 1.277
22 @@ -1,13 +1,13 @@
23 /*
24 * Copyright 2003-2012 Gentoo Foundation
25 * Distributed under the terms of the GNU General Public License v2
26 - * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.276 2015/02/28 22:57:40 vapier Exp $
27 + * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.277 2015/02/28 22:59:34 vapier Exp $
28 *
29 * Copyright 2003-2012 Ned Ludd - <solar@g.o>
30 * Copyright 2004-2012 Mike Frysinger - <vapier@g.o>
31 */
32
33 -static const char rcsid[] = "$Id: scanelf.c,v 1.276 2015/02/28 22:57:40 vapier Exp $";
34 +static const char rcsid[] = "$Id: scanelf.c,v 1.277 2015/02/28 22:59:34 vapier Exp $";
35 const char argv0[] = "scanelf";
36
37 #include "paxinc.h"
38 @@ -275,15 +275,23 @@
39 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
40 Elf ## B ## _Addr vaddr = EGET(phdr[i].p_vaddr); \
41 Elf ## B ## _Addr filesz = EGET(phdr[i].p_filesz); \
42 - offset = EGET(phdr[i].p_offset); \
43 + Elf ## B ## _Off hash_offset = offset + (vhash - vaddr); \
44 \
45 if (EGET(phdr[i].p_type) != PT_LOAD) \
46 continue; \
47 \
48 + offset = EGET(phdr[i].p_offset); \
49 + if (offset >= (uint64_t)elf->len) \
50 + goto corrupt_hash; \
51 + if (filesz >= (uint64_t)elf->len) \
52 + goto corrupt_hash; \
53 + if (hash_offset + (sizeof(Elf32_Word) * 4) > (uint64_t)elf->len) \
54 + goto corrupt_hash; \
55 + \
56 if (vhash >= vaddr && vhash < vaddr + filesz) { \
57 /* Scan the hash table to see how many entries we have */ \
58 Elf32_Word max_sym_idx = 0; \
59 - Elf32_Word *hashtbl = elf->vdata + offset + (vhash - vaddr); \
60 + Elf32_Word *hashtbl = elf->vdata + hash_offset; \
61 Elf32_Word b, nbuckets = EGET(hashtbl[0]); \
62 Elf32_Word nchains = EGET(hashtbl[1]); \
63 Elf32_Word *buckets = &hashtbl[2]; \
64 @@ -291,6 +299,17 @@
65 Elf32_Word sym_idx; \
66 Elf32_Word chained; \
67 \
68 + if (hash_offset >= (uint64_t)elf->len) \
69 + goto corrupt_hash; \
70 + if (nbuckets >= UINT32_MAX / 4) \
71 + goto corrupt_hash; \
72 + if (nchains >= UINT32_MAX / 4) \
73 + goto corrupt_hash; \
74 + if (nbuckets * 4 > elf->len - offset) \
75 + goto corrupt_hash; \
76 + if (nchains * 4 > elf->len - offset) \
77 + goto corrupt_hash; \
78 + \
79 for (b = 0; b < nbuckets; ++b) { \
80 if (!buckets[b]) \
81 continue; \
82 @@ -300,10 +319,8 @@
83 if (max_sym_idx < sym_idx) \
84 max_sym_idx = sym_idx; \
85 } \
86 - if (chained > nchains) { \
87 - warnf("corrupt ELF bucket"); \
88 - break; \
89 - } \
90 + if (chained > nchains) \
91 + goto corrupt_hash; \
92 } \
93 ESET(sym_shdr.sh_size, sym_shdr.sh_entsize * max_sym_idx); \
94 } \
95 @@ -321,6 +338,10 @@
96 }
97 GET_SYMTABS_DT(32)
98 GET_SYMTABS_DT(64)
99 + return;
100 +
101 + corrupt_hash:
102 + warn("%s: ELF hash table is corrupt", elf->filename);
103 }
104
105 static char *scanelf_file_pax(elfobj *elf, char *found_pax)
106 @@ -440,8 +461,9 @@
107 } else if (elf->shdr != NULL) { \
108 /* no program headers which means this is prob an object file */ \
109 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
110 - Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \
111 - if ((void*)strtbl > elf->data_end) \
112 + uint16_t shstrndx = EGET(ehdr->e_shstrndx); \
113 + Elf ## B ## _Shdr *strtbl = shdr + shstrndx; \
114 + if (shstrndx >= elf->len - sizeof(*strtbl) || !VALID_SHDR(elf, strtbl)) \
115 goto skip_this_shdr##B; \
116 /* let's flag -w/+x object files since the final ELF will most likely \
117 * need write access to the stack (who doesn't !?). so the combined \
118 @@ -1409,26 +1431,23 @@
119 if (cnt) \
120 cnt = EGET(symtab->sh_size) / cnt; \
121 for (i = 0; i < cnt; ++i) { \
122 - if ((void*)sym > elf->data_end) { \
123 - warnf("%s: corrupt ELF symbols - aborting", elf->filename); \
124 + if ((void *)sym >= elf->data_end - sizeof(*sym)) \
125 goto break_out; \
126 - } \
127 if (sym->st_name) { \
128 /* make sure the symbol name is in acceptable memory range */ \
129 symname = elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name); \
130 - if ((void*)symname > elf->data_end) { \
131 - warnf("%s: corrupt ELF symbols", elf->filename); \
132 - ++sym; \
133 - continue; \
134 - } \
135 + if (EGET(sym->st_name) >= (uint64_t)elf->len || \
136 + EGET(strtab->sh_offset) + EGET(sym->st_name) >= (uint64_t)elf->len || \
137 + !memchr(symname, 0, elf->len - EGET(strtab->sh_offset) + EGET(sym->st_name))) \
138 + goto break_out; \
139 scanelf_match_symname(elf, found_sym, \
140 - &ret, &ret_len, symname, \
141 - ELF##B##_ST_TYPE(EGET(sym->st_info)), \
142 - ELF##B##_ST_BIND(EGET(sym->st_info)), \
143 - ELF##B##_ST_VISIBILITY(EGET(sym->st_other)), \
144 - EGET(sym->st_shndx), \
145 - /* st_size can be 64bit, but no one is really that big, so screw em */ \
146 - EGET(sym->st_size)); \
147 + &ret, &ret_len, symname, \
148 + ELF##B##_ST_TYPE(EGET(sym->st_info)), \
149 + ELF##B##_ST_BIND(EGET(sym->st_info)), \
150 + ELF##B##_ST_VISIBILITY(EGET(sym->st_other)), \
151 + EGET(sym->st_shndx), \
152 + /* st_size can be 64bit, but no one is really that big, so screw em */ \
153 + EGET(sym->st_size)); \
154 } \
155 ++sym; \
156 } \
157 @@ -1437,7 +1456,6 @@
158 FIND_SYM(64)
159 }
160
161 -break_out:
162 if (be_wewy_wewy_quiet) return NULL;
163
164 if (*find_sym != '*' && *found_sym)
165 @@ -1446,6 +1464,10 @@
166 return NULL;
167 else
168 return " - ";
169 +
170 + break_out:
171 + warnf("%s: corrupt ELF symbols", elf->filename);
172 + return NULL;
173 }
174
175 static const char *scanelf_file_sections(elfobj *elf, char *found_section)