/[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.173 Revision 1.188
1/* 1/*
2 * Copyright 2003-2006 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/Attic/scanelf.c,v 1.173 2007/01/18 00:26:34 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.188 2007/08/31 17:45:24 solar Exp $
5 * 5 *
6 * Copyright 2003-2006 Ned Ludd - <solar@gentoo.org> 6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2004-2006 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.188 2007/08/31 17:45:24 solar Exp $";
11const char * const argv0 = "scanelf";
12
10#include "paxinc.h" 13#include "paxinc.h"
11
12static const char *rcsid = "$Id: scanelf.c,v 1.173 2007/01/18 00:26:34 vapier Exp $";
13#define argv0 "scanelf"
14 14
15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
16 16
17/* prototypes */ 17/* prototypes */
18static int file_matches_list(const char *filename, char **matchlist); 18static int file_matches_list(const char *filename, char **matchlist);
25static void scanelf_envpath(void); 25static void scanelf_envpath(void);
26static void usage(int status); 26static void usage(int status);
27static char **get_split_env(const char *envvar); 27static char **get_split_env(const char *envvar);
28static void parseenv(void); 28static void parseenv(void);
29static int parseargs(int argc, char *argv[]); 29static int parseargs(int argc, char *argv[]);
30static char *xstrdup(const char *s); 30static int rematch(const char *regex, const char *match, int cflags);
31static void *xmalloc(size_t size);
32static void *xrealloc(void *ptr, size_t size);
33static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n);
34#define xstrcat(dst,src,curr_len) xstrncat(dst,src,curr_len,0)
35static inline void xchrcat(char **dst, const char append, size_t *curr_len);
36 31
37/* variables to control behavior */ 32/* variables to control behavior */
38static char match_etypes[126] = ""; 33static char match_etypes[126] = "";
39static char *ldpaths[256]; 34static char *ldpaths[256];
40static char scan_ldpath = 0; 35static char scan_ldpath = 0;
42static char scan_symlink = 1; 37static char scan_symlink = 1;
43static char scan_archives = 0; 38static char scan_archives = 0;
44static char dir_recurse = 0; 39static char dir_recurse = 0;
45static char dir_crossmount = 1; 40static char dir_crossmount = 1;
46static char show_pax = 0; 41static char show_pax = 0;
42static char show_perms = 0;
47static char show_phdr = 0; 43static char show_phdr = 0;
48static char show_textrel = 0; 44static char show_textrel = 0;
49static char show_rpath = 0; 45static char show_rpath = 0;
50static char show_needed = 0; 46static char show_needed = 0;
51static char show_interp = 0; 47static char show_interp = 0;
52static char show_bind = 0; 48static char show_bind = 0;
53static char show_soname = 0; 49static char show_soname = 0;
54static char show_textrels = 0; 50static char show_textrels = 0;
55static char show_banner = 1; 51static char show_banner = 1;
52static char show_endian = 0;
56static char be_quiet = 0; 53static char be_quiet = 0;
57static char be_verbose = 0; 54static char be_verbose = 0;
58static char be_wewy_wewy_quiet = 0; 55static char be_wewy_wewy_quiet = 0;
59static char be_semi_verbose = 0; 56static char be_semi_verbose = 0;
60static char *find_sym = NULL, *versioned_symname = NULL; 57static char *find_sym = NULL, *versioned_symname = NULL;
61static char *find_lib = NULL; 58static char *find_lib = NULL;
62static char *find_section = NULL; 59static char *find_section = NULL;
63static char *out_format = NULL; 60static char *out_format = NULL;
64static char *search_path = NULL; 61static char *search_path = NULL;
65static char fix_elf = 0; 62static char fix_elf = 0;
66static char gmatch = 0; 63static char g_match = 0;
67static char use_ldcache = 0; 64static char use_ldcache = 0;
68 65
69static char **qa_textrels = NULL; 66static char **qa_textrels = NULL;
70static char **qa_execstack = NULL; 67static char **qa_execstack = NULL;
71static char **qa_wx_load = NULL; 68static char **qa_wx_load = NULL;
72 69
73int match_bits = 0; 70int match_bits = 0;
71unsigned int match_perms = 0;
74caddr_t ldcache = 0; 72caddr_t ldcache = 0;
75size_t ldcache_size = 0; 73size_t ldcache_size = 0;
76unsigned long setpax = 0UL; 74unsigned long setpax = 0UL;
77 75
78int has_objdump = 0; 76int has_objdump = 0;
79 77
78static char *getstr_perms(const char *fname);
79static char *getstr_perms(const char *fname)
80{
81 struct stat st;
82 static char buf[8];
83
84 if ((stat(fname, &st)) == (-1))
85 return (char *) "";
86
87 snprintf(buf, sizeof(buf), "%o", st.st_mode);
88
89 return (char *) buf + 2;
90}
91
92/* find the path to a file by name */
80static char *which(const char *fname) 93static char *which(const char *fname)
81{ 94{
82 static char fullpath[BUFSIZ]; 95 static char fullpath[BUFSIZ];
83 char *path, *p; 96 char *path, *p;
84 97
95 return (char *) fullpath; 108 return (char *) fullpath;
96 } 109 }
97 } 110 }
98 free(path); 111 free(path);
99 return NULL; 112 return NULL;
113}
114
115/* 1 on failure. 0 otherwise */
116static int rematch(const char *regex, const char *match, int cflags)
117{
118 regex_t preg;
119 int ret;
120
121 if ((match == NULL) || (regex == NULL))
122 return EXIT_FAILURE;
123
124
125 if ((ret = regcomp(&preg, regex, cflags))) {
126 char err[256];
127
128 if (regerror(ret, &preg, err, sizeof(err)))
129 fprintf(stderr, "regcomp failed: %s", err);
130 else
131 fprintf(stderr, "regcomp failed");
132
133 return EXIT_FAILURE;
134 }
135 ret = regexec(&preg, match, 0, NULL, 0);
136 regfree(&preg);
137
138 return ret;
100} 139}
101 140
102/* sub-funcs for scanelf_file() */ 141/* sub-funcs for scanelf_file() */
103static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab) 142static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab)
104{ 143{
227 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \ 266 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
228 found = found_relro; \ 267 found = found_relro; \
229 offset = 4; \ 268 offset = 4; \
230 check_flags = PF_X; \ 269 check_flags = PF_X; \
231 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \ 270 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
232 if (ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC) \ 271 if (EGET(ehdr->e_type) == ET_DYN || EGET(ehdr->e_type) == ET_EXEC) \
233 if (multi_load++ > max_pt_load) \ 272 if (multi_load++ > max_pt_load) \
234 warnf("%s: more than %i PT_LOAD's !?", elf->filename, max_pt_load); \ 273 warnf("%s: more than %i PT_LOAD's !?", elf->filename, max_pt_load); \
235 if (file_matches_list(elf->filename, qa_wx_load)) \ 274 if (file_matches_list(elf->filename, qa_wx_load)) \
236 continue; \ 275 continue; \
237 found = found_load; \ 276 found = found_load; \
295 return NULL; 334 return NULL;
296 else 335 else
297 return ret; 336 return ret;
298} 337}
299 338
339/*
340 * See if this ELF contains a DT_TEXTREL tag in any of its
341 * PT_DYNAMIC sections.
342 */
300static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 343static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
301{ 344{
302 static const char *ret = "TEXTREL"; 345 static const char *ret = "TEXTREL";
303 unsigned long i; 346 unsigned long i;
304 347
312 Elf ## B ## _Dyn *dyn; \ 355 Elf ## B ## _Dyn *dyn; \
313 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 356 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
314 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 357 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
315 Elf ## B ## _Off offset; \ 358 Elf ## B ## _Off offset; \
316 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 359 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
317 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 360 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
318 offset = EGET(phdr[i].p_offset); \ 361 offset = EGET(phdr[i].p_offset); \
319 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 362 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
320 dyn = DYN ## B (elf->data + offset); \ 363 dyn = DYN ## B (elf->data + offset); \
321 while (EGET(dyn->d_tag) != DT_NULL) { \ 364 while (EGET(dyn->d_tag) != DT_NULL) { \
322 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 365 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
334 if (be_quiet || be_wewy_wewy_quiet) 377 if (be_quiet || be_wewy_wewy_quiet)
335 return NULL; 378 return NULL;
336 else 379 else
337 return " - "; 380 return " - ";
338} 381}
382
383/*
384 * Scan the .text section to see if there are any relocations in it.
385 * Should rewrite this to check PT_LOAD sections that are marked
386 * Executable rather than the section named '.text'.
387 */
339static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel) 388static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel)
340{ 389{
341 unsigned long s, r, rmax; 390 unsigned long s, r, rmax;
342 void *symtab_void, *strtab_void, *text_void; 391 void *symtab_void, *strtab_void, *text_void;
343 392
434 printf("%s", func_name); \ 483 printf("%s", func_name); \
435 } else \ 484 } else \
436 printf("(optimized out)"); \ 485 printf("(optimized out)"); \
437 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \ 486 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \
438 if (be_verbose && has_objdump) { \ 487 if (be_verbose && has_objdump) { \
488 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
439 char *sysbuf; \ 489 char *sysbuf; \
440 size_t syslen; \ 490 size_t syslen; \
441 const char sysfmt[] = "objdump -r -R -d -w -l --start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 '.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \ 491 const char sysfmt[] = "objdump -r -R -d -w -l --start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 '.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \
442 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \ 492 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \
443 sysbuf = xmalloc(syslen); \ 493 sysbuf = xmalloc(syslen); \
444 if (sysbuf) { \
445 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
446 if (end_addr < r_offset) \ 494 if (end_addr < r_offset) \
447 /* not uncommon when things are optimized out */ \ 495 /* not uncommon when things are optimized out */ \
448 end_addr = r_offset + 0x100; \ 496 end_addr = r_offset + 0x100; \
449 snprintf(sysbuf, syslen, sysfmt, \ 497 snprintf(sysbuf, syslen, sysfmt, \
450 (unsigned long)offset_tmp, \ 498 (unsigned long)offset_tmp, \
451 (unsigned long)end_addr, \ 499 (unsigned long)end_addr, \
452 elf->filename, \ 500 elf->filename, \
453 (unsigned long)r_offset); \ 501 (unsigned long)r_offset); \
454 fflush(stdout); \ 502 fflush(stdout); \
455 system(sysbuf); \ 503 system(sysbuf); \
456 fflush(stdout); \ 504 fflush(stdout); \
457 free(sysbuf); \ 505 free(sysbuf); \
458 } \
459 } \ 506 } \
460 } \ 507 } \
461 } } 508 } }
462 SHOW_TEXTRELS(32) 509 SHOW_TEXTRELS(32)
463 SHOW_TEXTRELS(64) 510 SHOW_TEXTRELS(64)
483 break; 530 break;
484 case '$': 531 case '$':
485 if (fstat(elf->fd, &st) != -1) 532 if (fstat(elf->fd, &st) != -1)
486 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID)) 533 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID))
487 warnf("Security problem with %s='%s' in %s with mode set of %o", 534 warnf("Security problem with %s='%s' in %s with mode set of %o",
488 dt_type, item, elf->filename, st.st_mode & 07777); 535 dt_type, item, elf->filename, (unsigned int) st.st_mode & 07777);
489 break; 536 break;
490 default: 537 default:
491 warnf("Maybe? sec problem with %s='%s' in %s", dt_type, item, elf->filename); 538 warnf("Maybe? sec problem with %s='%s' in %s", dt_type, item, elf->filename);
492 break; 539 break;
493 } 540 }
513 Elf ## B ## _Off offset; \ 560 Elf ## B ## _Off offset; \
514 Elf ## B ## _Xword word; \ 561 Elf ## B ## _Xword word; \
515 /* Scan all the program headers */ \ 562 /* Scan all the program headers */ \
516 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 563 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
517 /* Just scan dynamic headers */ \ 564 /* Just scan dynamic headers */ \
518 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 565 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
519 offset = EGET(phdr[i].p_offset); \ 566 offset = EGET(phdr[i].p_offset); \
520 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 567 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
521 /* Just scan dynamic RPATH/RUNPATH headers */ \ 568 /* Just scan dynamic RPATH/RUNPATH headers */ \
522 dyn = DYN ## B (elf->data + offset); \ 569 dyn = DYN ## B (elf->data + offset); \
523 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \ 570 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
773 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 820 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
774 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 821 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
775 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 822 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
776 Elf ## B ## _Off offset; \ 823 Elf ## B ## _Off offset; \
777 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 824 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
778 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 825 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
779 offset = EGET(phdr[i].p_offset); \ 826 offset = EGET(phdr[i].p_offset); \
780 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 827 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
781 dyn = DYN ## B (elf->data + offset); \ 828 dyn = DYN ## B (elf->data + offset); \
782 while (EGET(dyn->d_tag) != DT_NULL) { \ 829 while (EGET(dyn->d_tag) != DT_NULL) { \
783 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 830 if (EGET(dyn->d_tag) == DT_NEEDED) { \
795 needed = p; \ 842 needed = p; \
796 xstrcat(ret, needed, ret_len); \ 843 xstrcat(ret, needed, ret_len); \
797 } \ 844 } \
798 *found_needed = 1; \ 845 *found_needed = 1; \
799 } else { \ 846 } else { \
800 if (!strncmp(find_lib, needed, strlen( !gmatch ? needed : find_lib))) { \ 847 if (!strncmp(find_lib, needed, strlen( !g_match ? needed : find_lib))) { \
801 *found_lib = 1; \ 848 *found_lib = 1; \
802 return (be_wewy_wewy_quiet ? NULL : needed); \ 849 return (be_wewy_wewy_quiet ? NULL : needed); \
803 } \ 850 } \
804 } \ 851 } \
805 } \ 852 } \
848 Elf ## B ## _Dyn *dyn; \ 895 Elf ## B ## _Dyn *dyn; \
849 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 896 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
850 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 897 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
851 Elf ## B ## _Off offset; \ 898 Elf ## B ## _Off offset; \
852 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 899 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
853 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 900 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
854 dynamic = 1; \ 901 dynamic = 1; \
855 offset = EGET(phdr[i].p_offset); \ 902 offset = EGET(phdr[i].p_offset); \
856 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 903 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
857 dyn = DYN ## B (elf->data + offset); \ 904 dyn = DYN ## B (elf->data + offset); \
858 while (EGET(dyn->d_tag) != DT_NULL) { \ 905 while (EGET(dyn->d_tag) != DT_NULL) { \
897 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 944 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
898 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 945 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
899 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 946 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
900 Elf ## B ## _Off offset; \ 947 Elf ## B ## _Off offset; \
901 /* only look for soname in shared objects */ \ 948 /* only look for soname in shared objects */ \
902 if (ehdr->e_type != ET_DYN) \ 949 if (EGET(ehdr->e_type) != ET_DYN) \
903 return NULL; \ 950 return NULL; \
904 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 951 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
905 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 952 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
906 offset = EGET(phdr[i].p_offset); \ 953 offset = EGET(phdr[i].p_offset); \
907 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 954 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
908 dyn = DYN ## B (elf->data + offset); \ 955 dyn = DYN ## B (elf->data + offset); \
909 while (EGET(dyn->d_tag) != DT_NULL) { \ 956 while (EGET(dyn->d_tag) != DT_NULL) { \
910 if (EGET(dyn->d_tag) == DT_SONAME) { \ 957 if (EGET(dyn->d_tag) == DT_SONAME) { \
924 SHOW_SONAME(64) 971 SHOW_SONAME(64)
925 } 972 }
926 973
927 return NULL; 974 return NULL;
928} 975}
976
929static char *scanelf_file_sym(elfobj *elf, char *found_sym) 977static char *scanelf_file_sym(elfobj *elf, char *found_sym)
930{ 978{
931 unsigned long i; 979 unsigned long i;
932 char *ret; 980 char *ret;
933 void *symtab_void, *strtab_void; 981 void *symtab_void, *strtab_void;
955 warnf("%s: corrupt ELF symbols", elf->filename); \ 1003 warnf("%s: corrupt ELF symbols", elf->filename); \
956 ++sym; \ 1004 ++sym; \
957 continue; \ 1005 continue; \
958 } \ 1006 } \
959 /* debug display ... show all symbols and some extra info */ \ 1007 /* debug display ... show all symbols and some extra info */ \
960 if (*ret == '*') { \ 1008 if (g_match ? rematch(ret, symname, REG_EXTENDED) == 0 : *ret == '*') { \
961 printf("%s(%s) %5lX %15s %s\n", \ 1009 printf("%s(%s) %5lX %15s %s %s\n", \
962 ((*found_sym == 0) ? "\n\t" : "\t"), \ 1010 ((*found_sym == 0) ? "\n\t" : "\t"), \
963 elf->base_filename, \ 1011 elf->base_filename, \
964 (unsigned long)sym->st_size, \ 1012 (unsigned long)sym->st_size, \
965 get_elfstttype(sym->st_info), \ 1013 get_elfstttype(sym->st_info), \
966 symname); \ 1014 sym->st_shndx == SHN_UNDEF ? "U" : "D", symname); \
967 *found_sym = 1; \ 1015 *found_sym = 1; \
968 } else { \ 1016 } else { \
969 /* allow the user to specify a comma delimited list of symbols to search for */ \ 1017 /* allow the user to specify a comma delimited list of symbols to search for */ \
970 char *this_sym, *this_sym_ver, *next_sym; \ 1018 char *this_sym, *this_sym_ver, *next_sym; \
971 this_sym = ret; \ 1019 this_sym = ret; \
1074 printf("%s: scanning file\n", elf->filename); 1122 printf("%s: scanning file\n", elf->filename);
1075 1123
1076 /* init output buffer */ 1124 /* init output buffer */
1077 if (!out_buffer) { 1125 if (!out_buffer) {
1078 out_len = sizeof(char) * 80; 1126 out_len = sizeof(char) * 80;
1079 out_buffer = (char*)xmalloc(out_len); 1127 out_buffer = xmalloc(out_len);
1080 } 1128 }
1081 *out_buffer = '\0'; 1129 *out_buffer = '\0';
1082 1130
1083 /* show the header */ 1131 /* show the header */
1084 if (!be_quiet && show_banner) { 1132 if (!be_quiet && show_banner) {
1105 case 's': prints("SYM "); break; 1153 case 's': prints("SYM "); break;
1106 case 'N': prints("LIB "); break; 1154 case 'N': prints("LIB "); break;
1107 case 'T': prints("TEXTRELS "); break; 1155 case 'T': prints("TEXTRELS "); break;
1108 case 'k': prints("SECTION "); break; 1156 case 'k': prints("SECTION "); break;
1109 case 'a': prints("ARCH "); break; 1157 case 'a': prints("ARCH "); break;
1158 case 'O': prints("PERM "); break;
1159 case 'D': prints("ENDIAN "); break;
1110 default: warnf("'%c' has no title ?", out_format[i]); 1160 default: warnf("'%c' has no title ?", out_format[i]);
1111 } 1161 }
1112 } 1162 }
1113 if (!found_file) prints("FILE "); 1163 if (!found_file) prints("FILE ");
1114 prints("\n"); 1164 prints("\n");
1165 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break; 1215 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break;
1166 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 1216 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
1167 case 'T': out = scanelf_file_textrels(elf, &found_textrels, &found_textrel); break; 1217 case 'T': out = scanelf_file_textrels(elf, &found_textrels, &found_textrel); break;
1168 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 1218 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
1169 case 'M': out = get_elfeitype(EI_CLASS, elf->data[EI_CLASS]); break; 1219 case 'M': out = get_elfeitype(EI_CLASS, elf->data[EI_CLASS]); break;
1220 case 'D': out = get_endian(elf); break;
1221 case 'O': out = getstr_perms(elf->filename); break;
1170 case 'n': 1222 case 'n':
1171 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break; 1223 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
1172 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 1224 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
1173 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 1225 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
1174 case 'S': out = scanelf_file_soname(elf, &found_soname); break; 1226 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
1228 if (strlen(match_etypes)) { 1280 if (strlen(match_etypes)) {
1229 char sbuf[126]; 1281 char sbuf[126];
1230 strncpy(sbuf, match_etypes, sizeof(sbuf)); 1282 strncpy(sbuf, match_etypes, sizeof(sbuf));
1231 if (strchr(match_etypes, ',') != NULL) { 1283 if (strchr(match_etypes, ',') != NULL) {
1232 char *p; 1284 char *p;
1233 while((p = strrchr(sbuf, ',')) != NULL) { 1285 while ((p = strrchr(sbuf, ',')) != NULL) {
1234 *p = 0; 1286 *p = 0;
1235 if (etype_lookup(p+1) == get_etype(elf)) 1287 if (etype_lookup(p+1) == get_etype(elf))
1236 goto label_ret; 1288 goto label_ret;
1237 } 1289 }
1238 } 1290 }
1289 if (!S_ISREG(st->st_mode)) { 1341 if (!S_ISREG(st->st_mode)) {
1290 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 1342 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
1291 return 1; 1343 return 1;
1292 } 1344 }
1293 1345
1346 if (match_perms) {
1347 if ((st->st_mode | match_perms) != st->st_mode)
1348 return 1;
1349 }
1294 if ((fd=open(filename, (fix_elf ? O_RDWR : O_RDONLY))) == -1) 1350 if ((fd=open(filename, (fix_elf ? O_RDWR : O_RDONLY))) == -1)
1295 return 1; 1351 return 1;
1296 1352
1297 if (scanelf_elf(filename, fd, st->st_size) == 1 && scan_archives) 1353 if (scanelf_elf(filename, fd, st->st_size) == 1 && scan_archives)
1298 /* if it isn't an ELF, maybe it's an .a archive */ 1354 /* if it isn't an ELF, maybe it's an .a archive */
1395 if ((p = strrchr(path, '\r')) != NULL) 1451 if ((p = strrchr(path, '\r')) != NULL)
1396 *p = 0; 1452 *p = 0;
1397 if ((p = strchr(path, '\n')) != NULL) 1453 if ((p = strchr(path, '\n')) != NULL)
1398 *p = 0; 1454 *p = 0;
1399#ifdef __linux__ 1455#ifdef __linux__
1400 // recursive includes of the same file will make this segfault. 1456 /* recursive includes of the same file will make this segfault. */
1401 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) { 1457 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) {
1402 glob64_t gl; 1458 glob64_t gl;
1403 size_t x; 1459 size_t x;
1404 char gpath[__PAX_UTILS_PATH_MAX]; 1460 char gpath[__PAX_UTILS_PATH_MAX];
1405 1461
1460 { 1516 {
1461 fclose(fp); 1517 fclose(fp);
1462 return i; 1518 return i;
1463 } 1519 }
1464 1520
1465 b = (char*)malloc(hdr.dirlistlen+1); 1521 b = xmalloc(hdr.dirlistlen + 1);
1466 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) { 1522 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) {
1467 fclose(fp); 1523 fclose(fp);
1468 free(b); 1524 free(b);
1469 return i; 1525 return i;
1470 } 1526 }
1492} 1548}
1493 1549
1494#endif 1550#endif
1495 1551
1496/* scan /etc/ld.so.conf for paths */ 1552/* scan /etc/ld.so.conf for paths */
1497static void scanelf_ldpath() 1553static void scanelf_ldpath(void)
1498{ 1554{
1499 char scan_l, scan_ul, scan_ull; 1555 char scan_l, scan_ul, scan_ull;
1500 int i = 0; 1556 int i = 0;
1501 1557
1502 if (!ldpaths[0]) 1558 if (!ldpaths[0])
1516 if (!scan_ul) scanelf_dir("/usr/lib"); 1572 if (!scan_ul) scanelf_dir("/usr/lib");
1517 if (!scan_ull) scanelf_dir("/usr/local/lib"); 1573 if (!scan_ull) scanelf_dir("/usr/local/lib");
1518} 1574}
1519 1575
1520/* scan env PATH for paths */ 1576/* scan env PATH for paths */
1521static void scanelf_envpath() 1577static void scanelf_envpath(void)
1522{ 1578{
1523 char *path, *p; 1579 char *path, *p;
1524 1580
1525 path = getenv("PATH"); 1581 path = getenv("PATH");
1526 if (!path) 1582 if (!path)
1533 } 1589 }
1534 1590
1535 free(path); 1591 free(path);
1536} 1592}
1537 1593
1538/* usage / invocation handling functions */ 1594
1595/* usage / invocation handling functions */ /* Free Flags: c d j u w C G H I J K P Q U W Y Z */
1539#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:BhV" 1596#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:DO:BhV"
1540#define a_argument required_argument 1597#define a_argument required_argument
1541static struct option const long_opts[] = { 1598static struct option const long_opts[] = {
1542 {"path", no_argument, NULL, 'p'}, 1599 {"path", no_argument, NULL, 'p'},
1543 {"ldpath", no_argument, NULL, 'l'}, 1600 {"ldpath", no_argument, NULL, 'l'},
1544 {"recursive", no_argument, NULL, 'R'}, 1601 {"recursive", no_argument, NULL, 'R'},
1561 {"lib", a_argument, NULL, 'N'}, 1618 {"lib", a_argument, NULL, 'N'},
1562 {"gmatch", no_argument, NULL, 'g'}, 1619 {"gmatch", no_argument, NULL, 'g'},
1563 {"textrels", no_argument, NULL, 'T'}, 1620 {"textrels", no_argument, NULL, 'T'},
1564 {"etype", a_argument, NULL, 'E'}, 1621 {"etype", a_argument, NULL, 'E'},
1565 {"bits", a_argument, NULL, 'M'}, 1622 {"bits", a_argument, NULL, 'M'},
1623 {"endian", no_argument, NULL, 'D'},
1624 {"perms", a_argument, NULL, 'O'},
1566 {"all", no_argument, NULL, 'a'}, 1625 {"all", no_argument, NULL, 'a'},
1567 {"quiet", no_argument, NULL, 'q'}, 1626 {"quiet", no_argument, NULL, 'q'},
1568 {"verbose", no_argument, NULL, 'v'}, 1627 {"verbose", no_argument, NULL, 'v'},
1569 {"format", a_argument, NULL, 'F'}, 1628 {"format", a_argument, NULL, 'F'},
1570 {"from", a_argument, NULL, 'f'}, 1629 {"from", a_argument, NULL, 'f'},
1598 "Find a specified library", 1657 "Find a specified library",
1599 "Use strncmp to match libraries. (use with -N)", 1658 "Use strncmp to match libraries. (use with -N)",
1600 "Locate cause of TEXTREL", 1659 "Locate cause of TEXTREL",
1601 "Print only ELF files matching etype ET_DYN,ET_EXEC ...", 1660 "Print only ELF files matching etype ET_DYN,ET_EXEC ...",
1602 "Print only ELF files matching numeric bits", 1661 "Print only ELF files matching numeric bits",
1662 "Print Endianness",
1663 "Print only ELF files matching octal permissions",
1603 "Print all scanned info (-x -e -t -r -b)\n", 1664 "Print all scanned info (-x -e -t -r -b)\n",
1604 "Only output 'bad' things", 1665 "Only output 'bad' things",
1605 "Be verbose (can be specified more than once)", 1666 "Be verbose (can be specified more than once)",
1606 "Use specified format for output", 1667 "Use specified format for output",
1607 "Read input stream from a filename", 1668 "Read input stream from a filename",
1664 case 'E': 1725 case 'E':
1665 strncpy(match_etypes, optarg, sizeof(match_etypes)); 1726 strncpy(match_etypes, optarg, sizeof(match_etypes));
1666 break; 1727 break;
1667 case 'M': 1728 case 'M':
1668 match_bits = atoi(optarg); 1729 match_bits = atoi(optarg);
1730 if (match_bits == 0) {
1731 if (strcmp(optarg, "ELFCLASS32") == 0)
1732 match_bits = 32;
1733 if (strcmp(optarg, "ELFCLASS64") == 0)
1734 match_bits = 64;
1735 }
1736 break;
1737 case 'O':
1738 if (sscanf(optarg, "%o", &match_perms) == (-1))
1739 match_bits = 0;
1669 break; 1740 break;
1670 case 'o': { 1741 case 'o': {
1671 if (freopen(optarg, "w", stdout) == NULL) 1742 if (freopen(optarg, "w", stdout) == NULL)
1672 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 1743 err("Could not open output stream '%s': %s", optarg, strerror(errno));
1673 break; 1744 break;
1677 find_section = optarg; 1748 find_section = optarg;
1678 break; 1749 break;
1679 case 's': { 1750 case 's': {
1680 if (find_sym) warn("You prob don't want to specify -s twice"); 1751 if (find_sym) warn("You prob don't want to specify -s twice");
1681 find_sym = optarg; 1752 find_sym = optarg;
1682 versioned_symname = (char*)xmalloc(sizeof(char) * (strlen(find_sym)+1+1)); 1753 versioned_symname = xmalloc(sizeof(char) * (strlen(find_sym)+1+1));
1683 sprintf(versioned_symname, "%s@", find_sym); 1754 sprintf(versioned_symname, "%s@", find_sym);
1684 break; 1755 break;
1685 } 1756 }
1686 case 'N': { 1757 case 'N': {
1687 if (find_lib) warn("You prob don't want to specify -N twice"); 1758 if (find_lib) warn("You prob don't want to specify -N twice");
1696 } 1767 }
1697 case 'z': { 1768 case 'z': {
1698 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC); 1769 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC);
1699 size_t x; 1770 size_t x;
1700 1771
1701 for (x = 0 ; x < strlen(optarg); x++) { 1772 for (x = 0; x < strlen(optarg); x++) {
1702 switch(optarg[x]) { 1773 switch (optarg[x]) {
1703 case 'p': 1774 case 'p':
1704 case 'P': 1775 case 'P':
1705 do_pax_state(optarg[x], PAGEEXEC); 1776 do_pax_state(optarg[x], PAGEEXEC);
1706 break; 1777 break;
1707 case 's': 1778 case 's':
1735 ((flags & PF_EMUTRAMP) && (flags & PF_NOEMUTRAMP)) || 1806 ((flags & PF_EMUTRAMP) && (flags & PF_NOEMUTRAMP)) ||
1736 ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP)))) 1807 ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP))))
1737 setpax = flags; 1808 setpax = flags;
1738 break; 1809 break;
1739 } 1810 }
1740 case 'g': gmatch = 1; break; 1811 case 'g': g_match = 1; break;
1741 case 'L': use_ldcache = 1; break; 1812 case 'L': use_ldcache = 1; break;
1742 case 'y': scan_symlink = 0; break; 1813 case 'y': scan_symlink = 0; break;
1743 case 'A': scan_archives = 1; break; 1814 case 'A': scan_archives = 1; break;
1744 case 'B': show_banner = 0; break; 1815 case 'B': show_banner = 0; break;
1745 case 'l': scan_ldpath = 1; break; 1816 case 'l': scan_ldpath = 1; break;
1756 case 'b': show_bind = 1; break; 1827 case 'b': show_bind = 1; break;
1757 case 'S': show_soname = 1; break; 1828 case 'S': show_soname = 1; break;
1758 case 'T': show_textrels = 1; break; 1829 case 'T': show_textrels = 1; break;
1759 case 'q': be_quiet = 1; break; 1830 case 'q': be_quiet = 1; break;
1760 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1831 case 'v': be_verbose = (be_verbose % 20) + 1; break;
1761 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break; 1832 case 'a': show_perms = show_pax = show_phdr = show_textrel = show_rpath = show_bind = show_endian = 1; break;
1762 1833 case 'D': show_endian = 1; break;
1763 case ':': 1834 case ':':
1764 err("Option '%c' is missing parameter", optopt); 1835 err("Option '%c' is missing parameter", optopt);
1765 case '?': 1836 case '?':
1766 err("Unknown option '%c' or argument missing", optopt); 1837 err("Unknown option '%c' or argument missing", optopt);
1767 default: 1838 default:
1774 } 1845 }
1775 /* let the format option override all other options */ 1846 /* let the format option override all other options */
1776 if (out_format) { 1847 if (out_format) {
1777 show_pax = show_phdr = show_textrel = show_rpath = \ 1848 show_pax = show_phdr = show_textrel = show_rpath = \
1778 show_needed = show_interp = show_bind = show_soname = \ 1849 show_needed = show_interp = show_bind = show_soname = \
1779 show_textrels = 0; 1850 show_textrels = show_perms = show_endian = 0;
1780 for (i = 0; out_format[i]; ++i) { 1851 for (i = 0; out_format[i]; ++i) {
1781 if (!IS_MODIFIER(out_format[i])) continue; 1852 if (!IS_MODIFIER(out_format[i])) continue;
1782 1853
1783 switch (out_format[++i]) { 1854 switch (out_format[++i]) {
1784 case '+': break; 1855 case '+': break;
1791 case 's': break; 1862 case 's': break;
1792 case 'N': break; 1863 case 'N': break;
1793 case 'o': break; 1864 case 'o': break;
1794 case 'a': break; 1865 case 'a': break;
1795 case 'M': break; 1866 case 'M': break;
1867 case 'D': show_endian = 1; break;
1868 case 'O': show_perms = 1; break;
1796 case 'x': show_pax = 1; break; 1869 case 'x': show_pax = 1; break;
1797 case 'e': show_phdr = 1; break; 1870 case 'e': show_phdr = 1; break;
1798 case 't': show_textrel = 1; break; 1871 case 't': show_textrel = 1; break;
1799 case 'r': show_rpath = 1; break; 1872 case 'r': show_rpath = 1; break;
1800 case 'n': show_needed = 1; break; 1873 case 'n': show_needed = 1; break;
1809 } 1882 }
1810 1883
1811 /* construct our default format */ 1884 /* construct our default format */
1812 } else { 1885 } else {
1813 size_t fmt_len = 30; 1886 size_t fmt_len = 30;
1814 out_format = (char*)xmalloc(sizeof(char) * fmt_len); 1887 out_format = xmalloc(sizeof(char) * fmt_len);
1815 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len); 1888 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
1816 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len); 1889 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len);
1890 if (show_perms) xstrcat(&out_format, "%O ", &fmt_len);
1891 if (show_endian) xstrcat(&out_format, "%D ", &fmt_len);
1817 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len); 1892 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len);
1818 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 1893 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
1819 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 1894 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
1820 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 1895 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
1821 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 1896 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
1888 1963
1889 /* don't want to free(env) as it contains the memory that backs 1964 /* don't want to free(env) as it contains the memory that backs
1890 * the envvals array of strings */ 1965 * the envvals array of strings */
1891 return envvals; 1966 return envvals;
1892} 1967}
1968
1893static void parseenv() 1969static void parseenv(void)
1894{ 1970{
1895 qa_textrels = get_split_env("QA_TEXTRELS"); 1971 qa_textrels = get_split_env("QA_TEXTRELS");
1896 qa_execstack = get_split_env("QA_EXECSTACK"); 1972 qa_execstack = get_split_env("QA_EXECSTACK");
1897 qa_wx_load = get_split_env("QA_WX_LOAD"); 1973 qa_wx_load = get_split_env("QA_WX_LOAD");
1898} 1974}
1899 1975
1900#ifdef __PAX_UTILS_CLEANUP 1976#ifdef __PAX_UTILS_CLEANUP
1901static void cleanup() 1977static void cleanup(void)
1902{ 1978{
1903 free(out_format); 1979 free(out_format);
1904 free(qa_textrels); 1980 free(qa_textrels);
1905 free(qa_execstack); 1981 free(qa_execstack);
1906 free(qa_wx_load); 1982 free(qa_wx_load);
1924#endif 2000#endif
1925 return ret; 2001 return ret;
1926} 2002}
1927 2003
1928 2004
1929
1930/* utility funcs */
1931static char *xstrdup(const char *s)
1932{
1933 char *ret = strdup(s);
1934 if (!ret) err("Could not strdup(): %s", strerror(errno));
1935 return ret;
1936}
1937static void *xmalloc(size_t size)
1938{
1939 void *ret = malloc(size);
1940 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
1941 return ret;
1942}
1943static void *xrealloc(void *ptr, size_t size)
1944{
1945 void *ret = realloc(ptr, size);
1946 if (!ret) err("Could not realloc() %li bytes", (unsigned long)size);
1947 return ret;
1948}
1949static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n)
1950{
1951 size_t new_len;
1952
1953 new_len = strlen(*dst) + strlen(src);
1954 if (*curr_len <= new_len) {
1955 *curr_len = new_len + (*curr_len / 2);
1956 *dst = realloc(*dst, *curr_len);
1957 if (!*dst)
1958 err("could not realloc() %li bytes", (unsigned long)*curr_len);
1959 }
1960
1961 if (n)
1962 strncat(*dst, src, n);
1963 else
1964 strcat(*dst, src);
1965}
1966static inline void xchrcat(char **dst, const char append, size_t *curr_len)
1967{
1968 static char my_app[2];
1969 my_app[0] = append;
1970 my_app[1] = '\0';
1971 xstrcat(dst, my_app, curr_len);
1972}
1973
1974/* Match filename against entries in matchlist, return TRUE 2005/* Match filename against entries in matchlist, return TRUE
1975 * if the file is listed */ 2006 * if the file is listed */
1976static int file_matches_list(const char *filename, char **matchlist) 2007static int file_matches_list(const char *filename, char **matchlist)
1977{ 2008{
1978 char **file; 2009 char **file;

Legend:
Removed from v.1.173  
changed lines
  Added in v.1.188

  ViewVC Help
Powered by ViewVC 1.1.20