/root/src/xen/xen/common/libelf/libelf-loader.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * parse and load elf binaries |
3 | | * |
4 | | * This library is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; |
7 | | * version 2.1 of the License. |
8 | | * |
9 | | * This library is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | | * Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with this library; If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | #ifdef __XEN__ |
19 | | #include <asm/guest_access.h> |
20 | | #endif |
21 | | |
22 | | #include "libelf-private.h" |
23 | | |
24 | | /* ------------------------------------------------------------------------ */ |
25 | | |
26 | | /* Number of section header needed in order to fit the SYMTAB and STRTAB. */ |
27 | 5 | #define ELF_BSDSYM_SECTIONS 3 |
28 | | struct elf_sym_header { |
29 | | uint32_t size; |
30 | | struct { |
31 | | elf_ehdr header; |
32 | | elf_shdr section[ELF_BSDSYM_SECTIONS]; |
33 | | } elf_header; |
34 | | } __attribute__((packed)); |
35 | | |
36 | | elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size) |
37 | 1 | { |
38 | 1 | ELF_HANDLE_DECL(elf_shdr) shdr; |
39 | 1 | unsigned i, count, section, link; |
40 | 1 | uint64_t offset; |
41 | 1 | |
42 | 1 | if ( !elf_is_elfbinary(image_input, size) ) |
43 | 0 | { |
44 | 0 | elf_err(elf, "ELF: not an ELF binary\n"); |
45 | 0 | return -1; |
46 | 0 | } |
47 | 1 | |
48 | 1 | elf_memset_unchecked(elf, 0, sizeof(*elf)); |
49 | 1 | elf->image_base = image_input; |
50 | 1 | elf->size = size; |
51 | 1 | elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input); |
52 | 1 | elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]); |
53 | 1 | elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]); |
54 | 1 | |
55 | 1 | /* Sanity check phdr. */ |
56 | 1 | offset = elf_uval(elf, elf->ehdr, e_phoff) + |
57 | 1 | elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); |
58 | 1 | if ( offset > elf->size ) |
59 | 0 | { |
60 | 0 | elf_err(elf, "ELF: phdr overflow (off %" PRIx64 " > size %lx)\n", |
61 | 0 | offset, (unsigned long)elf->size); |
62 | 0 | return -1; |
63 | 0 | } |
64 | 1 | |
65 | 1 | /* Sanity check shdr. */ |
66 | 1 | offset = elf_uval(elf, elf->ehdr, e_shoff) + |
67 | 1 | elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf); |
68 | 1 | if ( offset > elf->size ) |
69 | 0 | { |
70 | 0 | elf_err(elf, "ELF: shdr overflow (off %" PRIx64 " > size %lx)\n", |
71 | 0 | offset, (unsigned long)elf->size); |
72 | 0 | return -1; |
73 | 0 | } |
74 | 1 | |
75 | 1 | /* Find section string table. */ |
76 | 1 | section = elf_uval(elf, elf->ehdr, e_shstrndx); |
77 | 1 | shdr = elf_shdr_by_index(elf, section); |
78 | 1 | if ( ELF_HANDLE_VALID(shdr) ) |
79 | 1 | elf->sec_strtab = elf_section_start(elf, shdr); |
80 | 1 | |
81 | 1 | /* Find symbol table and symbol string table. */ |
82 | 1 | count = elf_shdr_count(elf); |
83 | 48 | for ( i = 1; i < count; i++ ) |
84 | 48 | { |
85 | 48 | shdr = elf_shdr_by_index(elf, i); |
86 | 48 | if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) ) |
87 | 48 | /* input has an insane section header count field */ |
88 | 0 | break; |
89 | 48 | if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB ) |
90 | 47 | continue; |
91 | 48 | |
92 | 1 | link = elf_uval(elf, shdr, sh_link); |
93 | 1 | if ( link == SHN_UNDEF || link >= count ) |
94 | 1 | /* out-of-bounds link value. */ |
95 | 0 | break; |
96 | 1 | |
97 | 1 | elf->sym_tab = shdr; |
98 | 1 | shdr = elf_shdr_by_index(elf, link); |
99 | 1 | if ( !ELF_HANDLE_VALID(shdr) ) |
100 | 0 | { |
101 | 0 | elf->sym_tab = ELF_INVALID_HANDLE(elf_shdr); |
102 | 0 | continue; |
103 | 0 | } |
104 | 1 | elf->sym_strtab = elf_section_start(elf, shdr); |
105 | 1 | break; |
106 | 1 | } |
107 | 1 | |
108 | 1 | return 0; |
109 | 1 | } |
110 | | |
111 | | #ifndef __XEN__ |
112 | | void elf_call_log_callback(struct elf_binary *elf, bool iserr, |
113 | | const char *fmt,...) { |
114 | | va_list al; |
115 | | |
116 | | if (!elf->log_callback) |
117 | | return; |
118 | | if (!(iserr || elf->verbose)) |
119 | | return; |
120 | | |
121 | | va_start(al,fmt); |
122 | | elf->log_callback(elf, elf->log_caller_data, iserr, fmt, al); |
123 | | va_end(al); |
124 | | } |
125 | | |
126 | | void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback, |
127 | | void *log_caller_data, bool verbose) |
128 | | { |
129 | | elf->log_callback = log_callback; |
130 | | elf->log_caller_data = log_caller_data; |
131 | | elf->verbose = verbose; |
132 | | } |
133 | | |
134 | | static elf_errorstatus elf_load_image(struct elf_binary *elf, |
135 | | elf_ptrval dst, elf_ptrval src, |
136 | | uint64_t filesz, uint64_t memsz) |
137 | | { |
138 | | elf_memcpy_safe(elf, dst, src, filesz); |
139 | | elf_memset_safe(elf, dst + filesz, 0, memsz - filesz); |
140 | | return 0; |
141 | | } |
142 | | #else |
143 | | |
144 | | void elf_set_verbose(struct elf_binary *elf) |
145 | 0 | { |
146 | 0 | elf->verbose = 1; |
147 | 0 | } |
148 | | |
149 | | static elf_errorstatus elf_memcpy(struct vcpu *v, void *dst, void *src, |
150 | | uint64_t size) |
151 | 16 | { |
152 | 16 | unsigned int res; |
153 | 16 | |
154 | 16 | #ifdef CONFIG_X86 |
155 | 16 | if ( is_hvm_vcpu(v) ) |
156 | 16 | { |
157 | 16 | enum hvm_translation_result rc; |
158 | 16 | |
159 | 16 | rc = hvm_copy_to_guest_phys((paddr_t)dst, src, size, v); |
160 | 16 | return rc != HVMTRANS_okay ? -1 : 0; |
161 | 16 | } |
162 | 16 | #endif |
163 | 16 | |
164 | 0 | res = src ? raw_copy_to_guest(dst, src, size) : |
165 | 0 | raw_clear_guest(dst, size); |
166 | 0 |
|
167 | 0 | return res ? -1 : 0; |
168 | 16 | } |
169 | | |
170 | | static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz) |
171 | 8 | { |
172 | 8 | elf_errorstatus rc; |
173 | 8 | if ( filesz > ULONG_MAX || memsz > ULONG_MAX ) |
174 | 0 | return -1; |
175 | 8 | /* We trust the dom0 kernel image completely, so we don't care |
176 | 8 | * about overruns etc. here. */ |
177 | 8 | rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), |
178 | 8 | filesz); |
179 | 8 | if ( rc != 0 ) |
180 | 0 | return -1; |
181 | 8 | rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst + filesz), NULL, |
182 | 8 | memsz - filesz); |
183 | 8 | if ( rc != 0 ) |
184 | 0 | return -1; |
185 | 8 | return 0; |
186 | 8 | } |
187 | | #endif |
188 | | |
189 | | /* Calculate the required additional kernel space for the elf image */ |
190 | | void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart) |
191 | 1 | { |
192 | 1 | uint64_t sz; |
193 | 1 | ELF_HANDLE_DECL(elf_shdr) shdr; |
194 | 1 | |
195 | 1 | if ( !ELF_HANDLE_VALID(elf->sym_tab) ) |
196 | 0 | { |
197 | 0 | elf_mark_broken(elf, "invalid ELF handle for symtab section"); |
198 | 0 | return; |
199 | 0 | } |
200 | 1 | |
201 | 1 | pstart = elf_round_up(elf, pstart); |
202 | 1 | |
203 | 1 | /* Space to store the size of the elf image */ |
204 | 1 | sz = sizeof(uint32_t); |
205 | 1 | |
206 | 1 | /* Space for the ELF header and section headers */ |
207 | 1 | sz += offsetof(struct elf_sym_header, elf_header.section) + |
208 | 1 | ELF_BSDSYM_SECTIONS * (elf_64bit(elf) ? sizeof(Elf64_Shdr) : |
209 | 0 | sizeof(Elf32_Shdr)); |
210 | 1 | sz = elf_round_up(elf, sz); |
211 | 1 | |
212 | 1 | /* |
213 | 1 | * No need to search for the symtab section header again, it's handler |
214 | 1 | * is stored in elf->sym_tab by the elf_init function. |
215 | 1 | */ |
216 | 1 | |
217 | 1 | /* Space for the symbol and string tables. */ |
218 | 1 | sz = elf_round_up(elf, sz + elf_uval(elf, elf->sym_tab, sh_size)); |
219 | 1 | |
220 | 1 | shdr = elf_shdr_by_index(elf, elf_uval(elf, elf->sym_tab, sh_link)); |
221 | 1 | |
222 | 1 | if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) ) |
223 | 1 | /* input has an insane section header count field */ |
224 | 0 | return; |
225 | 1 | |
226 | 1 | if ( elf_uval(elf, shdr, sh_type) != SHT_STRTAB ) |
227 | 1 | /* Invalid symtab -> strtab link */ |
228 | 0 | return; |
229 | 1 | |
230 | 1 | sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size)); |
231 | 1 | |
232 | 1 | elf->bsd_symtab_pstart = pstart; |
233 | 1 | elf->bsd_symtab_pend = pstart + sz; |
234 | 1 | } |
235 | | |
236 | | static void elf_load_bsdsyms(struct elf_binary *elf) |
237 | 1 | { |
238 | 1 | /* |
239 | 1 | * Header that is placed at the end of the kernel and allows |
240 | 1 | * the OS to find where the symtab and strtab have been loaded. |
241 | 1 | * It mimics a valid ELF file header, although it only contains |
242 | 1 | * a symtab and a strtab section. The layout in memory is the |
243 | 1 | * following: |
244 | 1 | * |
245 | 1 | * +------------------------+ |
246 | 1 | * | | |
247 | 1 | * | KERNEL | |
248 | 1 | * | | |
249 | 1 | * +------------------------+ pend |
250 | 1 | * | ALIGNMENT | |
251 | 1 | * +------------------------+ bsd_symtab_pstart |
252 | 1 | * | | |
253 | 1 | * | size | bsd_symtab_pend - bsd_symtab_pstart |
254 | 1 | * | | |
255 | 1 | * +------------------------+ bsd_symtab_pstart + 4 |
256 | 1 | * | | |
257 | 1 | * | ELF header | |
258 | 1 | * | | |
259 | 1 | * +------------------------+ |
260 | 1 | * | | |
261 | 1 | * | ELF section header 0 | Undefined section header |
262 | 1 | * | | |
263 | 1 | * +------------------------+ |
264 | 1 | * | | |
265 | 1 | * | ELF section header 1 | SYMTAB section header |
266 | 1 | * | | |
267 | 1 | * +------------------------+ |
268 | 1 | * | | |
269 | 1 | * | ELF section header 2 | STRTAB section header |
270 | 1 | * | | |
271 | 1 | * +------------------------+ |
272 | 1 | * | | |
273 | 1 | * | SYMTAB | |
274 | 1 | * | | |
275 | 1 | * +------------------------+ |
276 | 1 | * | | |
277 | 1 | * | STRTAB | |
278 | 1 | * | | |
279 | 1 | * +------------------------+ bsd_symtab_pend |
280 | 1 | * |
281 | 1 | * NB: according to the ELF spec there's only ONE symtab per ELF |
282 | 1 | * file, and accordingly we will only load the corresponding |
283 | 1 | * strtab, so we only need three section headers in our fake ELF |
284 | 1 | * header (first section header is always the undefined section). |
285 | 1 | */ |
286 | 1 | struct elf_sym_header header; |
287 | 1 | ELF_HANDLE_DECL(elf_ehdr) header_handle; |
288 | 1 | unsigned long shdr_size, ehdr_size, header_size; |
289 | 1 | ELF_HANDLE_DECL(elf_shdr) section_handle; |
290 | 1 | unsigned int link, rc, i; |
291 | 1 | elf_ptrval header_base; |
292 | 1 | elf_ptrval elf_header_base; |
293 | 1 | elf_ptrval symtab_base; |
294 | 1 | elf_ptrval strtab_base; |
295 | 1 | |
296 | 1 | if ( !elf->bsd_symtab_pstart ) |
297 | 0 | return; |
298 | 1 | |
299 | 12 | #define elf_store_field_bitness(_elf, _hdr, _elm, _val) \ |
300 | 12 | do { \ |
301 | 12 | if ( elf_64bit(_elf) ) \ |
302 | 12 | elf_store_field(_elf, _hdr, e64._elm, _val); \ |
303 | 12 | else \ |
304 | 0 | elf_store_field(_elf, _hdr, e32._elm, _val); \ |
305 | 12 | } while ( 0 ) |
306 | 1 | |
307 | 1 | #define SYMTAB_INDEX 1 |
308 | 1 | #define STRTAB_INDEX 2 |
309 | 1 | |
310 | 1 | /* Allow elf_memcpy_safe to write to header. */ |
311 | 1 | elf_set_xdest(elf, &header, sizeof(header)); |
312 | 1 | |
313 | 1 | /* |
314 | 1 | * Calculate the position of the various elements in GUEST MEMORY SPACE. |
315 | 1 | * This addresses MUST only be used with elf_load_image. |
316 | 1 | * |
317 | 1 | * NB: strtab_base cannot be calculated at this point because we don't |
318 | 1 | * know the size of the symtab yet, and the strtab will be placed after it. |
319 | 1 | */ |
320 | 1 | header_base = elf_get_ptr(elf, elf->bsd_symtab_pstart); |
321 | 1 | elf_header_base = elf_get_ptr(elf, elf->bsd_symtab_pstart) + |
322 | 1 | sizeof(uint32_t); |
323 | 1 | symtab_base = elf_round_up(elf, header_base + sizeof(header)); |
324 | 1 | |
325 | 1 | /* |
326 | 1 | * Set the size of the ELF header and the section headers, based on the |
327 | 1 | * size of our local copy. |
328 | 1 | */ |
329 | 1 | ehdr_size = elf_64bit(elf) ? sizeof(header.elf_header.header.e64) : |
330 | 0 | sizeof(header.elf_header.header.e32); |
331 | 1 | shdr_size = elf_64bit(elf) ? sizeof(header.elf_header.section[0].e64) : |
332 | 0 | sizeof(header.elf_header.section[0].e32); |
333 | 1 | |
334 | 1 | /* Fill the ELF header, copied from the original ELF header. */ |
335 | 1 | header_handle = ELF_MAKE_HANDLE(elf_ehdr, |
336 | 1 | ELF_REALPTR2PTRVAL(&header.elf_header.header)); |
337 | 1 | elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(header_handle), |
338 | 1 | ELF_HANDLE_PTRVAL(elf->ehdr), ehdr_size); |
339 | 1 | |
340 | 1 | /* |
341 | 1 | * Set the ELF header size, section header entry size and version |
342 | 1 | * (in case we are dealing with an input ELF header that has extensions). |
343 | 1 | */ |
344 | 1 | elf_store_field_bitness(elf, header_handle, e_ehsize, ehdr_size); |
345 | 1 | elf_store_field_bitness(elf, header_handle, e_shentsize, shdr_size); |
346 | 1 | elf_store_field_bitness(elf, header_handle, e_version, EV_CURRENT); |
347 | 1 | |
348 | 1 | /* Set the offset to the shdr array. */ |
349 | 1 | elf_store_field_bitness(elf, header_handle, e_shoff, |
350 | 1 | offsetof(typeof(header.elf_header), section)); |
351 | 1 | |
352 | 1 | /* Set the right number of section headers. */ |
353 | 1 | elf_store_field_bitness(elf, header_handle, e_shnum, ELF_BSDSYM_SECTIONS); |
354 | 1 | |
355 | 1 | /* Clear a couple of fields we don't use. */ |
356 | 1 | elf_store_field_bitness(elf, header_handle, e_phoff, 0); |
357 | 1 | elf_store_field_bitness(elf, header_handle, e_phentsize, 0); |
358 | 1 | elf_store_field_bitness(elf, header_handle, e_phnum, 0); |
359 | 1 | elf_store_field_bitness(elf, header_handle, e_shstrndx, 0); |
360 | 1 | |
361 | 1 | /* |
362 | 1 | * The symtab section header is going to reside in section[SYMTAB_INDEX], |
363 | 1 | * while the corresponding strtab is going to be placed in |
364 | 1 | * section[STRTAB_INDEX]. sh_offset is mangled so it points to the offset |
365 | 1 | * where the sections are actually loaded (relative to the ELF header |
366 | 1 | * location). |
367 | 1 | */ |
368 | 1 | section_handle = ELF_MAKE_HANDLE(elf_shdr, |
369 | 1 | ELF_REALPTR2PTRVAL(&header.elf_header.section[SYMTAB_INDEX])); |
370 | 1 | |
371 | 1 | elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(section_handle), |
372 | 1 | ELF_HANDLE_PTRVAL(elf->sym_tab), |
373 | 1 | shdr_size); |
374 | 1 | |
375 | 1 | /* Copy the original sh_link field before mangling it. */ |
376 | 1 | link = elf_uval(elf, section_handle, sh_link); |
377 | 1 | |
378 | 1 | /* Load symtab into guest memory. */ |
379 | 1 | rc = elf_load_image(elf, symtab_base, |
380 | 1 | elf_section_start(elf, section_handle), |
381 | 1 | elf_uval(elf, section_handle, sh_size), |
382 | 1 | elf_uval(elf, section_handle, sh_size)); |
383 | 1 | if ( rc != 0 ) |
384 | 0 | { |
385 | 0 | elf_mark_broken(elf, "unable to load symtab into guest memory"); |
386 | 0 | return; |
387 | 0 | } |
388 | 1 | |
389 | 1 | /* Adjust the sh_offset and sh_link of the copied section header. */ |
390 | 1 | elf_store_field_bitness(elf, section_handle, sh_offset, |
391 | 1 | symtab_base - elf_header_base); |
392 | 1 | elf_store_field_bitness(elf, section_handle, sh_link, |
393 | 1 | STRTAB_INDEX); |
394 | 1 | |
395 | 1 | /* Calculate the guest address where strtab is loaded. */ |
396 | 1 | strtab_base = elf_round_up(elf, symtab_base + |
397 | 1 | elf_uval(elf, section_handle, sh_size)); |
398 | 1 | |
399 | 1 | /* Load strtab section header. */ |
400 | 1 | section_handle = ELF_MAKE_HANDLE(elf_shdr, |
401 | 1 | ELF_REALPTR2PTRVAL(&header.elf_header.section[STRTAB_INDEX])); |
402 | 1 | elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(section_handle), |
403 | 1 | ELF_HANDLE_PTRVAL(elf_shdr_by_index(elf, link)), |
404 | 1 | shdr_size); |
405 | 1 | |
406 | 1 | if ( elf_uval(elf, section_handle, sh_type) != SHT_STRTAB ) |
407 | 0 | { |
408 | 0 | elf_mark_broken(elf, "strtab not found"); |
409 | 0 | return; |
410 | 0 | } |
411 | 1 | |
412 | 1 | /* Load strtab into guest memory. */ |
413 | 1 | rc = elf_load_image(elf, strtab_base, |
414 | 1 | elf_section_start(elf, section_handle), |
415 | 1 | elf_uval(elf, section_handle, sh_size), |
416 | 1 | elf_uval(elf, section_handle, sh_size)); |
417 | 1 | if ( rc != 0 ) |
418 | 0 | { |
419 | 0 | elf_mark_broken(elf, "unable to load strtab into guest memory"); |
420 | 0 | return; |
421 | 0 | } |
422 | 1 | |
423 | 1 | elf_store_field_bitness(elf, section_handle, sh_offset, |
424 | 1 | strtab_base - elf_header_base); |
425 | 1 | |
426 | 1 | /* Store the whole size (including headers and loaded sections). */ |
427 | 1 | header.size = strtab_base + elf_uval(elf, section_handle, sh_size) - |
428 | 1 | elf_header_base; |
429 | 1 | |
430 | 1 | /* Load the size plus ELF header. */ |
431 | 1 | header_size = offsetof(typeof(header), elf_header.section); |
432 | 1 | rc = elf_load_image(elf, header_base, ELF_REALPTR2PTRVAL(&header), |
433 | 1 | header_size, header_size); |
434 | 1 | if ( rc != 0 ) |
435 | 0 | { |
436 | 0 | elf_mark_broken(elf, "unable to load ELF headers into guest memory"); |
437 | 0 | return; |
438 | 0 | } |
439 | 1 | |
440 | 1 | /* |
441 | 1 | * Load the section headers. |
442 | 1 | * |
443 | 1 | * NB: this _must_ be done one by one, and taking the bitness into account, |
444 | 1 | * so that the guest can treat this as an array of type Elf{32/64}_Shdr. |
445 | 1 | */ |
446 | 4 | for ( i = 0; i < ELF_BSDSYM_SECTIONS; i++ ) |
447 | 3 | { |
448 | 3 | rc = elf_load_image(elf, header_base + header_size + shdr_size * i, |
449 | 3 | ELF_REALPTR2PTRVAL(&header.elf_header.section[i]), |
450 | 3 | shdr_size, shdr_size); |
451 | 3 | if ( rc != 0 ) |
452 | 0 | { |
453 | 0 | elf_mark_broken(elf, |
454 | 0 | "unable to load ELF section header into guest memory"); |
455 | 0 | return; |
456 | 0 | } |
457 | 3 | } |
458 | 1 | |
459 | 1 | /* Remove permissions from elf_memcpy_safe. */ |
460 | 1 | elf_set_xdest(elf, NULL, 0); |
461 | 1 | |
462 | 1 | #undef SYMTAB_INDEX |
463 | 1 | #undef STRTAB_INDEX |
464 | 1 | #undef elf_store_field_bitness |
465 | 1 | } |
466 | | |
467 | | void elf_parse_binary(struct elf_binary *elf) |
468 | 1 | { |
469 | 1 | ELF_HANDLE_DECL(elf_phdr) phdr; |
470 | 1 | uint64_t low = -1, high = 0, paddr, memsz; |
471 | 1 | unsigned i, count; |
472 | 1 | |
473 | 1 | count = elf_phdr_count(elf); |
474 | 7 | for ( i = 0; i < count; i++ ) |
475 | 6 | { |
476 | 6 | phdr = elf_phdr_by_index(elf, i); |
477 | 6 | if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) ) |
478 | 6 | /* input has an insane program header count field */ |
479 | 0 | break; |
480 | 6 | if ( !elf_phdr_is_loadable(elf, phdr) ) |
481 | 4 | continue; |
482 | 2 | paddr = elf_uval(elf, phdr, p_paddr); |
483 | 2 | memsz = elf_uval(elf, phdr, p_memsz); |
484 | 2 | elf_msg(elf, "ELF: phdr: paddr=%#" PRIx64 " memsz=%#" PRIx64 "\n", |
485 | 2 | paddr, memsz); |
486 | 2 | if ( low > paddr ) |
487 | 1 | low = paddr; |
488 | 2 | if ( high < paddr + memsz ) |
489 | 2 | high = paddr + memsz; |
490 | 2 | } |
491 | 1 | elf->pstart = low; |
492 | 1 | elf->pend = high; |
493 | 1 | elf_msg(elf, "ELF: memory: %#" PRIx64 " -> %#" PRIx64 "\n", |
494 | 1 | elf->pstart, elf->pend); |
495 | 1 | } |
496 | | |
497 | | elf_errorstatus elf_load_binary(struct elf_binary *elf) |
498 | 1 | { |
499 | 1 | ELF_HANDLE_DECL(elf_phdr) phdr; |
500 | 1 | uint64_t paddr, offset, filesz, memsz; |
501 | 1 | unsigned i, count; |
502 | 1 | elf_ptrval dest; |
503 | 1 | /* |
504 | 1 | * Let bizarre ELFs write the output image up to twice; this |
505 | 1 | * calculation is just to ensure our copying loop is no worse than |
506 | 1 | * O(domain_size). |
507 | 1 | */ |
508 | 1 | uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2; |
509 | 1 | |
510 | 1 | count = elf_phdr_count(elf); |
511 | 7 | for ( i = 0; i < count; i++ ) |
512 | 6 | { |
513 | 6 | phdr = elf_phdr_by_index(elf, i); |
514 | 6 | if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) ) |
515 | 6 | /* input has an insane program header count field */ |
516 | 0 | break; |
517 | 6 | if ( !elf_phdr_is_loadable(elf, phdr) ) |
518 | 4 | continue; |
519 | 2 | paddr = elf_uval(elf, phdr, p_paddr); |
520 | 2 | offset = elf_uval(elf, phdr, p_offset); |
521 | 2 | filesz = elf_uval(elf, phdr, p_filesz); |
522 | 2 | memsz = elf_uval(elf, phdr, p_memsz); |
523 | 2 | dest = elf_get_ptr(elf, paddr); |
524 | 2 | |
525 | 2 | /* |
526 | 2 | * We need to check that the input image doesn't have us copy |
527 | 2 | * the whole image zillions of times, as that could lead to |
528 | 2 | * O(n^2) time behaviour and possible DoS by a malicous ELF. |
529 | 2 | */ |
530 | 2 | if ( remain_allow_copy < memsz ) |
531 | 0 | { |
532 | 0 | elf_mark_broken(elf, "program segments total to more" |
533 | 0 | " than the input image size"); |
534 | 0 | break; |
535 | 0 | } |
536 | 2 | remain_allow_copy -= memsz; |
537 | 2 | |
538 | 2 | elf_msg(elf, |
539 | 2 | "ELF: phdr %u at %#"ELF_PRPTRVAL" -> %#"ELF_PRPTRVAL"\n", |
540 | 2 | i, dest, (elf_ptrval)(dest + filesz)); |
541 | 2 | if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 ) |
542 | 0 | return -1; |
543 | 2 | } |
544 | 1 | |
545 | 1 | elf_load_bsdsyms(elf); |
546 | 1 | return 0; |
547 | 1 | } |
548 | | |
549 | | elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr) |
550 | 4 | { |
551 | 4 | return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart; |
552 | 4 | } |
553 | | |
554 | | uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol) |
555 | 0 | { |
556 | 0 | ELF_HANDLE_DECL(elf_sym) sym; |
557 | 0 | uint64_t value; |
558 | 0 |
|
559 | 0 | sym = elf_sym_by_name(elf, symbol); |
560 | 0 | if ( !ELF_HANDLE_VALID(sym) ) |
561 | 0 | { |
562 | 0 | elf_err(elf, "%s: not found: %s\n", __func__, symbol); |
563 | 0 | return -1; |
564 | 0 | } |
565 | 0 |
|
566 | 0 | value = elf_uval(elf, sym, st_value); |
567 | 0 | elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __func__, |
568 | 0 | symbol, value); |
569 | 0 | return value; |
570 | 0 | } |
571 | | |
572 | | /* |
573 | | * Local variables: |
574 | | * mode: C |
575 | | * c-file-style: "BSD" |
576 | | * c-basic-offset: 4 |
577 | | * tab-width: 4 |
578 | | * indent-tabs-mode: nil |
579 | | * End: |
580 | | */ |