/[gentoo-projects]/pax-utils/scanelf.c
Gentoo

Diff of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.216 Revision 1.217
1/* 1/*
2 * Copyright 2003-2007 Gentoo Foundation 2 * Copyright 2003-2007 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.216 2009/12/20 20:25:04 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.217 2010/01/15 10:29:17 vapier Exp $
5 * 5 *
6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org> 6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org> 7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org>
8 */ 8 */
9 9
10static const char *rcsid = "$Id: scanelf.c,v 1.216 2009/12/20 20:25:04 vapier Exp $"; 10static const char *rcsid = "$Id: scanelf.c,v 1.217 2010/01/15 10:29:17 vapier Exp $";
11const char * const argv0 = "scanelf"; 11const char * const argv0 = "scanelf";
12 12
13#include "paxinc.h" 13#include "paxinc.h"
14 14
15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
282 } else if (elf->shdr != NULL) { \ 282 } else if (elf->shdr != NULL) { \
283 /* no program headers which means this is prob an object file */ \ 283 /* no program headers which means this is prob an object file */ \
284 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \ 284 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
285 Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \ 285 Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \
286 char *str; \ 286 char *str; \
287 if ((void*)strtbl > (void*)elf->data_end) \ 287 if ((void*)strtbl > elf->data_end) \
288 goto skip_this_shdr##B; \ 288 goto skip_this_shdr##B; \
289 check_flags = SHF_WRITE|SHF_EXECINSTR; \ 289 check_flags = SHF_WRITE|SHF_EXECINSTR; \
290 for (i = 0; i < EGET(ehdr->e_shnum); ++i) { \ 290 for (i = 0; i < EGET(ehdr->e_shnum); ++i) { \
291 if (EGET(shdr[i].sh_type) != SHT_PROGBITS) continue; \ 291 if (EGET(shdr[i].sh_type) != SHT_PROGBITS) continue; \
292 offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \ 292 offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \
347 Elf ## B ## _Off offset; \ 347 Elf ## B ## _Off offset; \
348 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 348 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
349 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 349 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
350 offset = EGET(phdr[i].p_offset); \ 350 offset = EGET(phdr[i].p_offset); \
351 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 351 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
352 dyn = DYN ## B (elf->data + offset); \ 352 dyn = DYN ## B (elf->vdata + offset); \
353 while (EGET(dyn->d_tag) != DT_NULL) { \ 353 while (EGET(dyn->d_tag) != DT_NULL) { \
354 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 354 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
355 *found_textrel = 1; \ 355 *found_textrel = 1; \
356 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 356 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
357 return (be_wewy_wewy_quiet ? NULL : ret); \ 357 return (be_wewy_wewy_quiet ? NULL : ret); \
402 Elf ## B ## _Rela *rela; \ 402 Elf ## B ## _Rela *rela; \
403 /* search the section headers for relocations */ \ 403 /* search the section headers for relocations */ \
404 for (s = 0; s < EGET(ehdr->e_shnum); ++s) { \ 404 for (s = 0; s < EGET(ehdr->e_shnum); ++s) { \
405 uint32_t sh_type = EGET(shdr[s].sh_type); \ 405 uint32_t sh_type = EGET(shdr[s].sh_type); \
406 if (sh_type == SHT_REL) { \ 406 if (sh_type == SHT_REL) { \
407 rel = REL ## B (elf->data + EGET(shdr[s].sh_offset)); \ 407 rel = REL ## B (elf->vdata + EGET(shdr[s].sh_offset)); \
408 rela = NULL; \ 408 rela = NULL; \
409 rmax = EGET(shdr[s].sh_size) / sizeof(*rel); \ 409 rmax = EGET(shdr[s].sh_size) / sizeof(*rel); \
410 } else if (sh_type == SHT_RELA) { \ 410 } else if (sh_type == SHT_RELA) { \
411 rel = NULL; \ 411 rel = NULL; \
412 rela = RELA ## B (elf->data + EGET(shdr[s].sh_offset)); \ 412 rela = RELA ## B (elf->vdata + EGET(shdr[s].sh_offset)); \
413 rmax = EGET(shdr[s].sh_size) / sizeof(*rela); \ 413 rmax = EGET(shdr[s].sh_size) / sizeof(*rela); \
414 } else \ 414 } else \
415 continue; \ 415 continue; \
416 /* now see if any of the relocs are in the .text */ \ 416 /* now see if any of the relocs are in the .text */ \
417 for (r = 0; r < rmax; ++r) { \ 417 for (r = 0; r < rmax; ++r) { \
432 if (r_offset < vaddr || r_offset >= vaddr + memsz) { \ 432 if (r_offset < vaddr || r_offset >= vaddr + memsz) { \
433 if (be_verbose <= 2) continue; \ 433 if (be_verbose <= 2) continue; \
434 } else \ 434 } else \
435 *found_textrels = 1; \ 435 *found_textrels = 1; \
436 /* locate this relocation symbol name */ \ 436 /* locate this relocation symbol name */ \
437 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 437 sym = SYM ## B (elf->vdata + EGET(symtab->sh_offset)); \
438 if ((void*)sym > (void*)elf->data_end) { \ 438 if ((void*)sym > elf->data_end) { \
439 warn("%s: corrupt ELF symbol", elf->filename); \ 439 warn("%s: corrupt ELF symbol", elf->filename); \
440 continue; \ 440 continue; \
441 } \ 441 } \
442 sym_max = ELF ## B ## _R_SYM(r_info); \ 442 sym_max = ELF ## B ## _R_SYM(r_info); \
443 if (sym_max * EGET(symtab->sh_entsize) < symtab->sh_size) \ 443 if (sym_max * EGET(symtab->sh_entsize) < symtab->sh_size) \
446 sym = NULL; \ 446 sym = NULL; \
447 sym_max = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 447 sym_max = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
448 /* show the raw details about this reloc */ \ 448 /* show the raw details about this reloc */ \
449 printf(" %s: ", elf->base_filename); \ 449 printf(" %s: ", elf->base_filename); \
450 if (sym && sym->st_name) \ 450 if (sym && sym->st_name) \
451 printf("%s", (char*)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name))); \ 451 printf("%s", elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
452 else \ 452 else \
453 printf("(memory/data?)"); \ 453 printf("(memory/data?)"); \
454 printf(" [0x%lX]", (unsigned long)r_offset); \ 454 printf(" [0x%lX]", (unsigned long)r_offset); \
455 /* now try to find the closest symbol that this rel is probably in */ \ 455 /* now try to find the closest symbol that this rel is probably in */ \
456 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 456 sym = SYM ## B (elf->vdata + EGET(symtab->sh_offset)); \
457 func = NULL; \ 457 func = NULL; \
458 offset_tmp = 0; \ 458 offset_tmp = 0; \
459 while (sym_max--) { \ 459 while (sym_max--) { \
460 if (EGET(sym->st_value) < r_offset && EGET(sym->st_value) > offset_tmp) { \ 460 if (EGET(sym->st_value) < r_offset && EGET(sym->st_value) > offset_tmp) { \
461 func = sym; \ 461 func = sym; \
554 /* Just scan dynamic headers */ \ 554 /* Just scan dynamic headers */ \
555 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 555 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
556 offset = EGET(phdr[i].p_offset); \ 556 offset = EGET(phdr[i].p_offset); \
557 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 557 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
558 /* Just scan dynamic RPATH/RUNPATH headers */ \ 558 /* Just scan dynamic RPATH/RUNPATH headers */ \
559 dyn = DYN ## B (elf->data + offset); \ 559 dyn = DYN ## B (elf->vdata + offset); \
560 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \ 560 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
561 if (word == DT_RPATH) { \ 561 if (word == DT_RPATH) { \
562 r = &rpath; \ 562 r = &rpath; \
563 } else if (word == DT_RUNPATH) { \ 563 } else if (word == DT_RUNPATH) { \
564 r = &runpath; \ 564 r = &runpath; \
568 } \ 568 } \
569 /* Verify the memory is somewhat sane */ \ 569 /* Verify the memory is somewhat sane */ \
570 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 570 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
571 if (offset < (Elf ## B ## _Off)elf->len) { \ 571 if (offset < (Elf ## B ## _Off)elf->len) { \
572 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \ 572 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
573 *r = (char*)(elf->data + offset); \ 573 *r = elf->data + offset; \
574 /* cache the length in case we need to nuke this section later on */ \ 574 /* cache the length in case we need to nuke this section later on */ \
575 if (fix_elf) \ 575 if (fix_elf) \
576 offset = strlen(*r); \ 576 offset = strlen(*r); \
577 /* If quiet, don't output paths in ld.so.conf */ \ 577 /* If quiet, don't output paths in ld.so.conf */ \
578 if (be_quiet) { \ 578 if (be_quiet) { \
827 Elf ## B ## _Off offset; \ 827 Elf ## B ## _Off offset; \
828 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 828 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
829 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 829 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
830 offset = EGET(phdr[i].p_offset); \ 830 offset = EGET(phdr[i].p_offset); \
831 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 831 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
832 dyn = DYN ## B (elf->data + offset); \ 832 dyn = DYN ## B (elf->vdata + offset); \
833 while (EGET(dyn->d_tag) != DT_NULL) { \ 833 while (EGET(dyn->d_tag) != DT_NULL) { \
834 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 834 if (EGET(dyn->d_tag) == DT_NEEDED) { \
835 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 835 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
836 if (offset >= (Elf ## B ## _Off)elf->len) { \ 836 if (offset >= (Elf ## B ## _Off)elf->len) { \
837 ++dyn; \ 837 ++dyn; \
838 continue; \ 838 continue; \
839 } \ 839 } \
840 needed = (char*)(elf->data + offset); \ 840 needed = elf->data + offset; \
841 if (op == 0) { \ 841 if (op == 0) { \
842 if (!be_wewy_wewy_quiet) { \ 842 if (!be_wewy_wewy_quiet) { \
843 if (*found_needed) xchrcat(ret, ',', ret_len); \ 843 if (*found_needed) xchrcat(ret, ',', ret_len); \
844 if (use_ldcache) \ 844 if (use_ldcache) \
845 if ((p = lookup_cache_lib(elf, needed)) != NULL) \ 845 if ((p = lookup_cache_lib(elf, needed)) != NULL) \
903 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 903 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
904 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 904 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
905 dynamic = 1; \ 905 dynamic = 1; \
906 offset = EGET(phdr[i].p_offset); \ 906 offset = EGET(phdr[i].p_offset); \
907 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 907 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
908 dyn = DYN ## B (elf->data + offset); \ 908 dyn = DYN ## B (elf->vdata + offset); \
909 while (EGET(dyn->d_tag) != DT_NULL) { \ 909 while (EGET(dyn->d_tag) != DT_NULL) { \
910 if (EGET(dyn->d_tag) == DT_BIND_NOW || \ 910 if (EGET(dyn->d_tag) == DT_BIND_NOW || \
911 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \ 911 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \
912 { \ 912 { \
913 if (be_quiet) return NULL; \ 913 if (be_quiet) return NULL; \
926 /* don't output anything if quiet mode and the ELF is static or not setuid */ 926 /* don't output anything if quiet mode and the ELF is static or not setuid */
927 if (be_quiet && (!dynamic || (!fstat(elf->fd, &s) && !(s.st_mode & (S_ISUID|S_ISGID))))) { 927 if (be_quiet && (!dynamic || (!fstat(elf->fd, &s) && !(s.st_mode & (S_ISUID|S_ISGID))))) {
928 return NULL; 928 return NULL;
929 } else { 929 } else {
930 *found_bind = 1; 930 *found_bind = 1;
931 return (char *) (dynamic ? "LAZY" : "STATIC"); 931 return (char *)(dynamic ? "LAZY" : "STATIC");
932 } 932 }
933} 933}
934static char *scanelf_file_soname(elfobj *elf, char *found_soname) 934static char *scanelf_file_soname(elfobj *elf, char *found_soname)
935{ 935{
936 unsigned long i; 936 unsigned long i;
954 return NULL; \ 954 return NULL; \
955 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 955 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
956 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 956 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
957 offset = EGET(phdr[i].p_offset); \ 957 offset = EGET(phdr[i].p_offset); \
958 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 958 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
959 dyn = DYN ## B (elf->data + offset); \ 959 dyn = DYN ## B (elf->vdata + offset); \
960 while (EGET(dyn->d_tag) != DT_NULL) { \ 960 while (EGET(dyn->d_tag) != DT_NULL) { \
961 if (EGET(dyn->d_tag) == DT_SONAME) { \ 961 if (EGET(dyn->d_tag) == DT_SONAME) { \
962 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 962 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
963 if (offset >= (Elf ## B ## _Off)elf->len) { \ 963 if (offset >= (Elf ## B ## _Off)elf->len) { \
964 ++dyn; \ 964 ++dyn; \
965 continue; \ 965 continue; \
966 } \ 966 } \
967 soname = (char*)(elf->data + offset); \ 967 soname = elf->data + offset; \
968 *found_soname = 1; \ 968 *found_soname = 1; \
969 return (be_wewy_wewy_quiet ? NULL : soname); \ 969 return (be_wewy_wewy_quiet ? NULL : soname); \
970 } \ 970 } \
971 ++dyn; \ 971 ++dyn; \
972 } \ 972 } \
1159 if (symtab_void && strtab_void) { 1159 if (symtab_void && strtab_void) {
1160#define FIND_SYM(B) \ 1160#define FIND_SYM(B) \
1161 if (elf->elf_class == ELFCLASS ## B) { \ 1161 if (elf->elf_class == ELFCLASS ## B) { \
1162 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 1162 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
1163 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 1163 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
1164 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 1164 Elf ## B ## _Sym *sym = SYM ## B (elf->vdata + EGET(symtab->sh_offset)); \
1165 unsigned long cnt = EGET(symtab->sh_entsize); \ 1165 unsigned long cnt = EGET(symtab->sh_entsize); \
1166 char *symname; \ 1166 char *symname; \
1167 size_t ret_len = 0; \ 1167 size_t ret_len = 0; \
1168 if (cnt) \ 1168 if (cnt) \
1169 cnt = EGET(symtab->sh_size) / cnt; \ 1169 cnt = EGET(symtab->sh_size) / cnt; \
1170 for (i = 0; i < cnt; ++i) { \ 1170 for (i = 0; i < cnt; ++i) { \
1171 if ((void*)sym > (void*)elf->data_end) { \ 1171 if ((void*)sym > elf->data_end) { \
1172 warnf("%s: corrupt ELF symbols - aborting", elf->filename); \ 1172 warnf("%s: corrupt ELF symbols - aborting", elf->filename); \
1173 goto break_out; \ 1173 goto break_out; \
1174 } \ 1174 } \
1175 if (sym->st_name) { \ 1175 if (sym->st_name) { \
1176 /* make sure the symbol name is in acceptable memory range */ \ 1176 /* make sure the symbol name is in acceptable memory range */ \
1177 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 1177 symname = elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name); \
1178 if ((void*)symname > (void*)elf->data_end) { \ 1178 if ((void*)symname > elf->data_end) { \
1179 warnf("%s: corrupt ELF symbols", elf->filename); \ 1179 warnf("%s: corrupt ELF symbols", elf->filename); \
1180 ++sym; \ 1180 ++sym; \
1181 continue; \ 1181 continue; \
1182 } \ 1182 } \
1183 scanelf_match_symname(elf, found_sym, \ 1183 scanelf_match_symname(elf, found_sym, \

Legend:
Removed from v.1.216  
changed lines
  Added in v.1.217

  ViewVC Help
Powered by ViewVC 1.1.20