/[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.178 Revision 1.188
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/Attic/scanelf.c,v 1.178 2007/05/23 22:27:27 solar 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.178 2007/05/23 22:27:27 solar 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);
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);
36static int rematch(const char *regex, const char *match, int cflags); 30static int rematch(const char *regex, const char *match, int cflags);
37 31
38/* variables to control behavior */ 32/* variables to control behavior */
39static char match_etypes[126] = ""; 33static char match_etypes[126] = "";
40static char *ldpaths[256]; 34static char *ldpaths[256];
43static char scan_symlink = 1; 37static char scan_symlink = 1;
44static char scan_archives = 0; 38static char scan_archives = 0;
45static char dir_recurse = 0; 39static char dir_recurse = 0;
46static char dir_crossmount = 1; 40static char dir_crossmount = 1;
47static char show_pax = 0; 41static char show_pax = 0;
42static char show_perms = 0;
48static char show_phdr = 0; 43static char show_phdr = 0;
49static char show_textrel = 0; 44static char show_textrel = 0;
50static char show_rpath = 0; 45static char show_rpath = 0;
51static char show_needed = 0; 46static char show_needed = 0;
52static char show_interp = 0; 47static char show_interp = 0;
53static char show_bind = 0; 48static char show_bind = 0;
54static char show_soname = 0; 49static char show_soname = 0;
55static char show_textrels = 0; 50static char show_textrels = 0;
56static char show_banner = 1; 51static char show_banner = 1;
52static char show_endian = 0;
57static char be_quiet = 0; 53static char be_quiet = 0;
58static char be_verbose = 0; 54static char be_verbose = 0;
59static char be_wewy_wewy_quiet = 0; 55static char be_wewy_wewy_quiet = 0;
60static char be_semi_verbose = 0; 56static char be_semi_verbose = 0;
61static char *find_sym = NULL, *versioned_symname = NULL; 57static char *find_sym = NULL, *versioned_symname = NULL;
70static char **qa_textrels = NULL; 66static char **qa_textrels = NULL;
71static char **qa_execstack = NULL; 67static char **qa_execstack = NULL;
72static char **qa_wx_load = NULL; 68static char **qa_wx_load = NULL;
73 69
74int match_bits = 0; 70int match_bits = 0;
71unsigned int match_perms = 0;
75caddr_t ldcache = 0; 72caddr_t ldcache = 0;
76size_t ldcache_size = 0; 73size_t ldcache_size = 0;
77unsigned long setpax = 0UL; 74unsigned long setpax = 0UL;
78 75
79int has_objdump = 0; 76int has_objdump = 0;
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}
80 91
81/* find the path to a file by name */ 92/* find the path to a file by name */
82static char *which(const char *fname) 93static char *which(const char *fname)
83{ 94{
84 static char fullpath[BUFSIZ]; 95 static char fullpath[BUFSIZ];
255 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \ 266 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
256 found = found_relro; \ 267 found = found_relro; \
257 offset = 4; \ 268 offset = 4; \
258 check_flags = PF_X; \ 269 check_flags = PF_X; \
259 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \ 270 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
260 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) \
261 if (multi_load++ > max_pt_load) \ 272 if (multi_load++ > max_pt_load) \
262 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); \
263 if (file_matches_list(elf->filename, qa_wx_load)) \ 274 if (file_matches_list(elf->filename, qa_wx_load)) \
264 continue; \ 275 continue; \
265 found = found_load; \ 276 found = found_load; \
323 return NULL; 334 return NULL;
324 else 335 else
325 return ret; 336 return ret;
326} 337}
327 338
339/*
340 * See if this ELF contains a DT_TEXTREL tag in any of its
341 * PT_DYNAMIC sections.
342 */
328static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 343static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
329{ 344{
330 static const char *ret = "TEXTREL"; 345 static const char *ret = "TEXTREL";
331 unsigned long i; 346 unsigned long i;
332 347
340 Elf ## B ## _Dyn *dyn; \ 355 Elf ## B ## _Dyn *dyn; \
341 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 356 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
342 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 357 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
343 Elf ## B ## _Off offset; \ 358 Elf ## B ## _Off offset; \
344 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 359 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
345 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; \
346 offset = EGET(phdr[i].p_offset); \ 361 offset = EGET(phdr[i].p_offset); \
347 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 362 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
348 dyn = DYN ## B (elf->data + offset); \ 363 dyn = DYN ## B (elf->data + offset); \
349 while (EGET(dyn->d_tag) != DT_NULL) { \ 364 while (EGET(dyn->d_tag) != DT_NULL) { \
350 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)*/ \
362 if (be_quiet || be_wewy_wewy_quiet) 377 if (be_quiet || be_wewy_wewy_quiet)
363 return NULL; 378 return NULL;
364 else 379 else
365 return " - "; 380 return " - ";
366} 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 */
367static 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)
368{ 389{
369 unsigned long s, r, rmax; 390 unsigned long s, r, rmax;
370 void *symtab_void, *strtab_void, *text_void; 391 void *symtab_void, *strtab_void, *text_void;
371 392
462 printf("%s", func_name); \ 483 printf("%s", func_name); \
463 } else \ 484 } else \
464 printf("(optimized out)"); \ 485 printf("(optimized out)"); \
465 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \ 486 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \
466 if (be_verbose && has_objdump) { \ 487 if (be_verbose && has_objdump) { \
488 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
467 char *sysbuf; \ 489 char *sysbuf; \
468 size_t syslen; \ 490 size_t syslen; \
469 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"; \
470 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \ 492 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \
471 sysbuf = xmalloc(syslen); \ 493 sysbuf = xmalloc(syslen); \
472 if (sysbuf) { \
473 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
474 if (end_addr < r_offset) \ 494 if (end_addr < r_offset) \
475 /* not uncommon when things are optimized out */ \ 495 /* not uncommon when things are optimized out */ \
476 end_addr = r_offset + 0x100; \ 496 end_addr = r_offset + 0x100; \
477 snprintf(sysbuf, syslen, sysfmt, \ 497 snprintf(sysbuf, syslen, sysfmt, \
478 (unsigned long)offset_tmp, \ 498 (unsigned long)offset_tmp, \
479 (unsigned long)end_addr, \ 499 (unsigned long)end_addr, \
480 elf->filename, \ 500 elf->filename, \
481 (unsigned long)r_offset); \ 501 (unsigned long)r_offset); \
482 fflush(stdout); \ 502 fflush(stdout); \
483 system(sysbuf); \ 503 system(sysbuf); \
484 fflush(stdout); \ 504 fflush(stdout); \
485 free(sysbuf); \ 505 free(sysbuf); \
486 } \
487 } \ 506 } \
488 } \ 507 } \
489 } } 508 } }
490 SHOW_TEXTRELS(32) 509 SHOW_TEXTRELS(32)
491 SHOW_TEXTRELS(64) 510 SHOW_TEXTRELS(64)
541 Elf ## B ## _Off offset; \ 560 Elf ## B ## _Off offset; \
542 Elf ## B ## _Xword word; \ 561 Elf ## B ## _Xword word; \
543 /* Scan all the program headers */ \ 562 /* Scan all the program headers */ \
544 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 563 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
545 /* Just scan dynamic headers */ \ 564 /* Just scan dynamic headers */ \
546 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; \
547 offset = EGET(phdr[i].p_offset); \ 566 offset = EGET(phdr[i].p_offset); \
548 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 567 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
549 /* Just scan dynamic RPATH/RUNPATH headers */ \ 568 /* Just scan dynamic RPATH/RUNPATH headers */ \
550 dyn = DYN ## B (elf->data + offset); \ 569 dyn = DYN ## B (elf->data + offset); \
551 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \ 570 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
801 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 820 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
802 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 821 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
803 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 822 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
804 Elf ## B ## _Off offset; \ 823 Elf ## B ## _Off offset; \
805 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 824 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
806 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; \
807 offset = EGET(phdr[i].p_offset); \ 826 offset = EGET(phdr[i].p_offset); \
808 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 827 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
809 dyn = DYN ## B (elf->data + offset); \ 828 dyn = DYN ## B (elf->data + offset); \
810 while (EGET(dyn->d_tag) != DT_NULL) { \ 829 while (EGET(dyn->d_tag) != DT_NULL) { \
811 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 830 if (EGET(dyn->d_tag) == DT_NEEDED) { \
876 Elf ## B ## _Dyn *dyn; \ 895 Elf ## B ## _Dyn *dyn; \
877 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 896 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
878 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 897 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
879 Elf ## B ## _Off offset; \ 898 Elf ## B ## _Off offset; \
880 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 899 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
881 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; \
882 dynamic = 1; \ 901 dynamic = 1; \
883 offset = EGET(phdr[i].p_offset); \ 902 offset = EGET(phdr[i].p_offset); \
884 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 903 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
885 dyn = DYN ## B (elf->data + offset); \ 904 dyn = DYN ## B (elf->data + offset); \
886 while (EGET(dyn->d_tag) != DT_NULL) { \ 905 while (EGET(dyn->d_tag) != DT_NULL) { \
925 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 944 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
926 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 945 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
927 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 946 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
928 Elf ## B ## _Off offset; \ 947 Elf ## B ## _Off offset; \
929 /* only look for soname in shared objects */ \ 948 /* only look for soname in shared objects */ \
930 if (ehdr->e_type != ET_DYN) \ 949 if (EGET(ehdr->e_type) != ET_DYN) \
931 return NULL; \ 950 return NULL; \
932 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 951 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
933 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; \
934 offset = EGET(phdr[i].p_offset); \ 953 offset = EGET(phdr[i].p_offset); \
935 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 954 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
936 dyn = DYN ## B (elf->data + offset); \ 955 dyn = DYN ## B (elf->data + offset); \
937 while (EGET(dyn->d_tag) != DT_NULL) { \ 956 while (EGET(dyn->d_tag) != DT_NULL) { \
938 if (EGET(dyn->d_tag) == DT_SONAME) { \ 957 if (EGET(dyn->d_tag) == DT_SONAME) { \
1103 printf("%s: scanning file\n", elf->filename); 1122 printf("%s: scanning file\n", elf->filename);
1104 1123
1105 /* init output buffer */ 1124 /* init output buffer */
1106 if (!out_buffer) { 1125 if (!out_buffer) {
1107 out_len = sizeof(char) * 80; 1126 out_len = sizeof(char) * 80;
1108 out_buffer = (char*)xmalloc(out_len); 1127 out_buffer = xmalloc(out_len);
1109 } 1128 }
1110 *out_buffer = '\0'; 1129 *out_buffer = '\0';
1111 1130
1112 /* show the header */ 1131 /* show the header */
1113 if (!be_quiet && show_banner) { 1132 if (!be_quiet && show_banner) {
1134 case 's': prints("SYM "); break; 1153 case 's': prints("SYM "); break;
1135 case 'N': prints("LIB "); break; 1154 case 'N': prints("LIB "); break;
1136 case 'T': prints("TEXTRELS "); break; 1155 case 'T': prints("TEXTRELS "); break;
1137 case 'k': prints("SECTION "); break; 1156 case 'k': prints("SECTION "); break;
1138 case 'a': prints("ARCH "); break; 1157 case 'a': prints("ARCH "); break;
1158 case 'O': prints("PERM "); break;
1159 case 'D': prints("ENDIAN "); break;
1139 default: warnf("'%c' has no title ?", out_format[i]); 1160 default: warnf("'%c' has no title ?", out_format[i]);
1140 } 1161 }
1141 } 1162 }
1142 if (!found_file) prints("FILE "); 1163 if (!found_file) prints("FILE ");
1143 prints("\n"); 1164 prints("\n");
1194 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;
1195 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 1216 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
1196 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;
1197 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;
1198 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;
1199 case 'n': 1222 case 'n':
1200 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;
1201 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 1224 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
1202 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 1225 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
1203 case 'S': out = scanelf_file_soname(elf, &found_soname); break; 1226 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
1257 if (strlen(match_etypes)) { 1280 if (strlen(match_etypes)) {
1258 char sbuf[126]; 1281 char sbuf[126];
1259 strncpy(sbuf, match_etypes, sizeof(sbuf)); 1282 strncpy(sbuf, match_etypes, sizeof(sbuf));
1260 if (strchr(match_etypes, ',') != NULL) { 1283 if (strchr(match_etypes, ',') != NULL) {
1261 char *p; 1284 char *p;
1262 while((p = strrchr(sbuf, ',')) != NULL) { 1285 while ((p = strrchr(sbuf, ',')) != NULL) {
1263 *p = 0; 1286 *p = 0;
1264 if (etype_lookup(p+1) == get_etype(elf)) 1287 if (etype_lookup(p+1) == get_etype(elf))
1265 goto label_ret; 1288 goto label_ret;
1266 } 1289 }
1267 } 1290 }
1318 if (!S_ISREG(st->st_mode)) { 1341 if (!S_ISREG(st->st_mode)) {
1319 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 1342 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
1320 return 1; 1343 return 1;
1321 } 1344 }
1322 1345
1346 if (match_perms) {
1347 if ((st->st_mode | match_perms) != st->st_mode)
1348 return 1;
1349 }
1323 if ((fd=open(filename, (fix_elf ? O_RDWR : O_RDONLY))) == -1) 1350 if ((fd=open(filename, (fix_elf ? O_RDWR : O_RDONLY))) == -1)
1324 return 1; 1351 return 1;
1325 1352
1326 if (scanelf_elf(filename, fd, st->st_size) == 1 && scan_archives) 1353 if (scanelf_elf(filename, fd, st->st_size) == 1 && scan_archives)
1327 /* 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 */
1424 if ((p = strrchr(path, '\r')) != NULL) 1451 if ((p = strrchr(path, '\r')) != NULL)
1425 *p = 0; 1452 *p = 0;
1426 if ((p = strchr(path, '\n')) != NULL) 1453 if ((p = strchr(path, '\n')) != NULL)
1427 *p = 0; 1454 *p = 0;
1428#ifdef __linux__ 1455#ifdef __linux__
1429 // recursive includes of the same file will make this segfault. 1456 /* recursive includes of the same file will make this segfault. */
1430 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) { 1457 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) {
1431 glob64_t gl; 1458 glob64_t gl;
1432 size_t x; 1459 size_t x;
1433 char gpath[__PAX_UTILS_PATH_MAX]; 1460 char gpath[__PAX_UTILS_PATH_MAX];
1434 1461
1489 { 1516 {
1490 fclose(fp); 1517 fclose(fp);
1491 return i; 1518 return i;
1492 } 1519 }
1493 1520
1494 b = (char*)malloc(hdr.dirlistlen+1); 1521 b = xmalloc(hdr.dirlistlen + 1);
1495 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) { 1522 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) {
1496 fclose(fp); 1523 fclose(fp);
1497 free(b); 1524 free(b);
1498 return i; 1525 return i;
1499 } 1526 }
1521} 1548}
1522 1549
1523#endif 1550#endif
1524 1551
1525/* scan /etc/ld.so.conf for paths */ 1552/* scan /etc/ld.so.conf for paths */
1526static void scanelf_ldpath() 1553static void scanelf_ldpath(void)
1527{ 1554{
1528 char scan_l, scan_ul, scan_ull; 1555 char scan_l, scan_ul, scan_ull;
1529 int i = 0; 1556 int i = 0;
1530 1557
1531 if (!ldpaths[0]) 1558 if (!ldpaths[0])
1545 if (!scan_ul) scanelf_dir("/usr/lib"); 1572 if (!scan_ul) scanelf_dir("/usr/lib");
1546 if (!scan_ull) scanelf_dir("/usr/local/lib"); 1573 if (!scan_ull) scanelf_dir("/usr/local/lib");
1547} 1574}
1548 1575
1549/* scan env PATH for paths */ 1576/* scan env PATH for paths */
1550static void scanelf_envpath() 1577static void scanelf_envpath(void)
1551{ 1578{
1552 char *path, *p; 1579 char *path, *p;
1553 1580
1554 path = getenv("PATH"); 1581 path = getenv("PATH");
1555 if (!path) 1582 if (!path)
1562 } 1589 }
1563 1590
1564 free(path); 1591 free(path);
1565} 1592}
1566 1593
1567/* 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 */
1568#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"
1569#define a_argument required_argument 1597#define a_argument required_argument
1570static struct option const long_opts[] = { 1598static struct option const long_opts[] = {
1571 {"path", no_argument, NULL, 'p'}, 1599 {"path", no_argument, NULL, 'p'},
1572 {"ldpath", no_argument, NULL, 'l'}, 1600 {"ldpath", no_argument, NULL, 'l'},
1573 {"recursive", no_argument, NULL, 'R'}, 1601 {"recursive", no_argument, NULL, 'R'},
1590 {"lib", a_argument, NULL, 'N'}, 1618 {"lib", a_argument, NULL, 'N'},
1591 {"gmatch", no_argument, NULL, 'g'}, 1619 {"gmatch", no_argument, NULL, 'g'},
1592 {"textrels", no_argument, NULL, 'T'}, 1620 {"textrels", no_argument, NULL, 'T'},
1593 {"etype", a_argument, NULL, 'E'}, 1621 {"etype", a_argument, NULL, 'E'},
1594 {"bits", a_argument, NULL, 'M'}, 1622 {"bits", a_argument, NULL, 'M'},
1623 {"endian", no_argument, NULL, 'D'},
1624 {"perms", a_argument, NULL, 'O'},
1595 {"all", no_argument, NULL, 'a'}, 1625 {"all", no_argument, NULL, 'a'},
1596 {"quiet", no_argument, NULL, 'q'}, 1626 {"quiet", no_argument, NULL, 'q'},
1597 {"verbose", no_argument, NULL, 'v'}, 1627 {"verbose", no_argument, NULL, 'v'},
1598 {"format", a_argument, NULL, 'F'}, 1628 {"format", a_argument, NULL, 'F'},
1599 {"from", a_argument, NULL, 'f'}, 1629 {"from", a_argument, NULL, 'f'},
1627 "Find a specified library", 1657 "Find a specified library",
1628 "Use strncmp to match libraries. (use with -N)", 1658 "Use strncmp to match libraries. (use with -N)",
1629 "Locate cause of TEXTREL", 1659 "Locate cause of TEXTREL",
1630 "Print only ELF files matching etype ET_DYN,ET_EXEC ...", 1660 "Print only ELF files matching etype ET_DYN,ET_EXEC ...",
1631 "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",
1632 "Print all scanned info (-x -e -t -r -b)\n", 1664 "Print all scanned info (-x -e -t -r -b)\n",
1633 "Only output 'bad' things", 1665 "Only output 'bad' things",
1634 "Be verbose (can be specified more than once)", 1666 "Be verbose (can be specified more than once)",
1635 "Use specified format for output", 1667 "Use specified format for output",
1636 "Read input stream from a filename", 1668 "Read input stream from a filename",
1693 case 'E': 1725 case 'E':
1694 strncpy(match_etypes, optarg, sizeof(match_etypes)); 1726 strncpy(match_etypes, optarg, sizeof(match_etypes));
1695 break; 1727 break;
1696 case 'M': 1728 case 'M':
1697 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;
1698 break; 1740 break;
1699 case 'o': { 1741 case 'o': {
1700 if (freopen(optarg, "w", stdout) == NULL) 1742 if (freopen(optarg, "w", stdout) == NULL)
1701 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 1743 err("Could not open output stream '%s': %s", optarg, strerror(errno));
1702 break; 1744 break;
1706 find_section = optarg; 1748 find_section = optarg;
1707 break; 1749 break;
1708 case 's': { 1750 case 's': {
1709 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");
1710 find_sym = optarg; 1752 find_sym = optarg;
1711 versioned_symname = (char*)xmalloc(sizeof(char) * (strlen(find_sym)+1+1)); 1753 versioned_symname = xmalloc(sizeof(char) * (strlen(find_sym)+1+1));
1712 sprintf(versioned_symname, "%s@", find_sym); 1754 sprintf(versioned_symname, "%s@", find_sym);
1713 break; 1755 break;
1714 } 1756 }
1715 case 'N': { 1757 case 'N': {
1716 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");
1725 } 1767 }
1726 case 'z': { 1768 case 'z': {
1727 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC); 1769 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC);
1728 size_t x; 1770 size_t x;
1729 1771
1730 for (x = 0 ; x < strlen(optarg); x++) { 1772 for (x = 0; x < strlen(optarg); x++) {
1731 switch(optarg[x]) { 1773 switch (optarg[x]) {
1732 case 'p': 1774 case 'p':
1733 case 'P': 1775 case 'P':
1734 do_pax_state(optarg[x], PAGEEXEC); 1776 do_pax_state(optarg[x], PAGEEXEC);
1735 break; 1777 break;
1736 case 's': 1778 case 's':
1785 case 'b': show_bind = 1; break; 1827 case 'b': show_bind = 1; break;
1786 case 'S': show_soname = 1; break; 1828 case 'S': show_soname = 1; break;
1787 case 'T': show_textrels = 1; break; 1829 case 'T': show_textrels = 1; break;
1788 case 'q': be_quiet = 1; break; 1830 case 'q': be_quiet = 1; break;
1789 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1831 case 'v': be_verbose = (be_verbose % 20) + 1; break;
1790 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;
1791 1833 case 'D': show_endian = 1; break;
1792 case ':': 1834 case ':':
1793 err("Option '%c' is missing parameter", optopt); 1835 err("Option '%c' is missing parameter", optopt);
1794 case '?': 1836 case '?':
1795 err("Unknown option '%c' or argument missing", optopt); 1837 err("Unknown option '%c' or argument missing", optopt);
1796 default: 1838 default:
1803 } 1845 }
1804 /* let the format option override all other options */ 1846 /* let the format option override all other options */
1805 if (out_format) { 1847 if (out_format) {
1806 show_pax = show_phdr = show_textrel = show_rpath = \ 1848 show_pax = show_phdr = show_textrel = show_rpath = \
1807 show_needed = show_interp = show_bind = show_soname = \ 1849 show_needed = show_interp = show_bind = show_soname = \
1808 show_textrels = 0; 1850 show_textrels = show_perms = show_endian = 0;
1809 for (i = 0; out_format[i]; ++i) { 1851 for (i = 0; out_format[i]; ++i) {
1810 if (!IS_MODIFIER(out_format[i])) continue; 1852 if (!IS_MODIFIER(out_format[i])) continue;
1811 1853
1812 switch (out_format[++i]) { 1854 switch (out_format[++i]) {
1813 case '+': break; 1855 case '+': break;
1820 case 's': break; 1862 case 's': break;
1821 case 'N': break; 1863 case 'N': break;
1822 case 'o': break; 1864 case 'o': break;
1823 case 'a': break; 1865 case 'a': break;
1824 case 'M': break; 1866 case 'M': break;
1867 case 'D': show_endian = 1; break;
1868 case 'O': show_perms = 1; break;
1825 case 'x': show_pax = 1; break; 1869 case 'x': show_pax = 1; break;
1826 case 'e': show_phdr = 1; break; 1870 case 'e': show_phdr = 1; break;
1827 case 't': show_textrel = 1; break; 1871 case 't': show_textrel = 1; break;
1828 case 'r': show_rpath = 1; break; 1872 case 'r': show_rpath = 1; break;
1829 case 'n': show_needed = 1; break; 1873 case 'n': show_needed = 1; break;
1838 } 1882 }
1839 1883
1840 /* construct our default format */ 1884 /* construct our default format */
1841 } else { 1885 } else {
1842 size_t fmt_len = 30; 1886 size_t fmt_len = 30;
1843 out_format = (char*)xmalloc(sizeof(char) * fmt_len); 1887 out_format = xmalloc(sizeof(char) * fmt_len);
1844 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len); 1888 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
1845 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);
1846 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len); 1892 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len);
1847 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 1893 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
1848 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 1894 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
1849 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 1895 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
1850 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 1896 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
1917 1963
1918 /* 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
1919 * the envvals array of strings */ 1965 * the envvals array of strings */
1920 return envvals; 1966 return envvals;
1921} 1967}
1968
1922static void parseenv() 1969static void parseenv(void)
1923{ 1970{
1924 qa_textrels = get_split_env("QA_TEXTRELS"); 1971 qa_textrels = get_split_env("QA_TEXTRELS");
1925 qa_execstack = get_split_env("QA_EXECSTACK"); 1972 qa_execstack = get_split_env("QA_EXECSTACK");
1926 qa_wx_load = get_split_env("QA_WX_LOAD"); 1973 qa_wx_load = get_split_env("QA_WX_LOAD");
1927} 1974}
1928 1975
1929#ifdef __PAX_UTILS_CLEANUP 1976#ifdef __PAX_UTILS_CLEANUP
1930static void cleanup() 1977static void cleanup(void)
1931{ 1978{
1932 free(out_format); 1979 free(out_format);
1933 free(qa_textrels); 1980 free(qa_textrels);
1934 free(qa_execstack); 1981 free(qa_execstack);
1935 free(qa_wx_load); 1982 free(qa_wx_load);
1953#endif 2000#endif
1954 return ret; 2001 return ret;
1955} 2002}
1956 2003
1957 2004
1958
1959/* utility funcs */
1960static char *xstrdup(const char *s)
1961{
1962 char *ret = strdup(s);
1963 if (!ret) err("Could not strdup(): %s", strerror(errno));
1964 return ret;
1965}
1966static void *xmalloc(size_t size)
1967{
1968 void *ret = malloc(size);
1969 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
1970 return ret;
1971}
1972static void *xrealloc(void *ptr, size_t size)
1973{
1974 void *ret = realloc(ptr, size);
1975 if (!ret) err("Could not realloc() %li bytes", (unsigned long)size);
1976 return ret;
1977}
1978static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n)
1979{
1980 size_t new_len;
1981
1982 new_len = strlen(*dst) + strlen(src);
1983 if (*curr_len <= new_len) {
1984 *curr_len = new_len + (*curr_len / 2);
1985 *dst = realloc(*dst, *curr_len);
1986 if (!*dst)
1987 err("could not realloc() %li bytes", (unsigned long)*curr_len);
1988 }
1989
1990 if (n)
1991 strncat(*dst, src, n);
1992 else
1993 strcat(*dst, src);
1994}
1995static inline void xchrcat(char **dst, const char append, size_t *curr_len)
1996{
1997 static char my_app[2];
1998 my_app[0] = append;
1999 my_app[1] = '\0';
2000 xstrcat(dst, my_app, curr_len);
2001}
2002
2003/* Match filename against entries in matchlist, return TRUE 2005/* Match filename against entries in matchlist, return TRUE
2004 * if the file is listed */ 2006 * if the file is listed */
2005static int file_matches_list(const char *filename, char **matchlist) 2007static int file_matches_list(const char *filename, char **matchlist)
2006{ 2008{
2007 char **file; 2009 char **file;

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

  ViewVC Help
Powered by ViewVC 1.1.20