/[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.61 Revision 1.69
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 2 * Copyright 2003-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.69 2005/06/03 23:18:01 vapier Exp $
6 * 5 *
7 ******************************************************************** 6 ********************************************************************
8 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 8 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
34#include <dirent.h> 33#include <dirent.h>
35#include <getopt.h> 34#include <getopt.h>
36#include <assert.h> 35#include <assert.h>
37#include "paxelf.h" 36#include "paxelf.h"
38 37
39static const char *rcsid = "$Id: scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.69 2005/06/03 23:18:01 vapier Exp $";
40#define argv0 "scanelf" 39#define argv0 "scanelf"
41 40
42 41
43 42
44/* prototypes */ 43/* prototypes */
70static char show_banner = 1; 69static char show_banner = 1;
71static char be_quiet = 0; 70static char be_quiet = 0;
72static char be_verbose = 0; 71static char be_verbose = 0;
73static char *find_sym = NULL, *versioned_symname = NULL; 72static char *find_sym = NULL, *versioned_symname = NULL;
74static char *out_format = NULL; 73static char *out_format = NULL;
74static char *search_path = NULL;
75 75
76 76
77/* sub-funcs for scanelf_file() */ 77/* sub-funcs for scanelf_file() */
78static char *scanelf_file_pax(elfobj *elf, char *found_pax) 78static char *scanelf_file_pax(elfobj *elf, char *found_pax)
79{ 79{
163 else 163 else
164 return ret; 164 return ret;
165} 165}
166static char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 166static char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
167{ 167{
168 static char *ret = "TEXTREL"; 168 static char ret[] = "TEXTREL";
169 unsigned long i; 169 unsigned long i;
170 170
171 if (!show_textrel) return NULL; 171 if (!show_textrel) return NULL;
172 172
173 if (elf->phdr) { 173 if (elf->phdr) {
196 } 196 }
197 197
198 if (be_quiet) 198 if (be_quiet)
199 return NULL; 199 return NULL;
200 else 200 else
201 return " - "; 201 return (char *)" - ";
202} 202}
203static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 203static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
204{ 204{
205 /* TODO: when checking RPATH entries, check each subpath (between :) in ld.so.conf */
206 unsigned long i, s; 205 unsigned long i, s;
207 char *rpath, *runpath, **r; 206 char *rpath, *runpath, **r;
208 void *strtbl_void; 207 void *strtbl_void;
209 208
210 if (!show_rpath) return; 209 if (!show_rpath) return;
238 ++dyn; \ 237 ++dyn; \
239 continue; \ 238 continue; \
240 } \ 239 } \
241 /* Verify the memory is somewhat sane */ \ 240 /* Verify the memory is somewhat sane */ \
242 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 241 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
243 if (offset < elf->len) { \ 242 if (offset < (Elf ## B ## _Off)elf->len) { \
244 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \ 243 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
245 *r = (char*)(elf->data + offset); \ 244 *r = (char*)(elf->data + offset); \
246 /* If quiet, don't output paths in ld.so.conf */ \ 245 /* If quiet, don't output paths in ld.so.conf */ \
247 if (be_quiet) \ 246 if (be_quiet) { \
247 size_t len; \
248 char *start, *end; \
248 for (s = 0; ldpaths[s]; ++s) \ 249 for (s = 0; *r && ldpaths[s]; ++s) { \
249 if (!strcmp(ldpaths[s], *r)) { \ 250 /* scan each path in : delimited list */ \
250 *r = NULL; \ 251 start = *r; \
252 end = strchr(start, ':'); \
253 while ((start && ((end = strchr(start, ':')) != NULL)) || start) { \
254 len = (end ? abs(end - start) : strlen(start)); \
255 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \
256 *r = (end ? end + 1 : NULL); \
251 break; \ 257 break; \
258 } \
259 start = (end ? start + len + 1 : NULL); \
252 } \ 260 } \
261 } \
262 } \
253 if (*r) *found_rpath = 1; \ 263 if (*r) *found_rpath = 1; \
254 } \ 264 } \
255 ++dyn; \ 265 ++dyn; \
256 } \ 266 } \
257 } } 267 } }
299 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 309 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
300 dyn = DYN ## B (elf->data + offset); \ 310 dyn = DYN ## B (elf->data + offset); \
301 while (EGET(dyn->d_tag) != DT_NULL) { \ 311 while (EGET(dyn->d_tag) != DT_NULL) { \
302 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 312 if (EGET(dyn->d_tag) == DT_NEEDED) { \
303 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 313 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
304 if (offset >= elf->len) { \ 314 if (offset >= (Elf ## B ## _Off)elf->len) { \
305 ++dyn; \ 315 ++dyn; \
306 continue; \ 316 continue; \
307 } \ 317 } \
308 needed = (char*)(elf->data + offset); \ 318 needed = (char*)(elf->data + offset); \
309 if (*found_needed) xchrcat(ret, ',', ret_len); \ 319 if (*found_needed) xchrcat(ret, ',', ret_len); \
360 if (EGET(dyn->d_tag) == DT_BIND_NOW || \ 370 if (EGET(dyn->d_tag) == DT_BIND_NOW || \
361 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \ 371 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \
362 { \ 372 { \
363 if (be_quiet) return NULL; \ 373 if (be_quiet) return NULL; \
364 *found_bind = 1; \ 374 *found_bind = 1; \
365 return "NOW"; \ 375 return (char *) "NOW"; \
366 } \ 376 } \
367 ++dyn; \ 377 ++dyn; \
368 } \ 378 } \
369 } \ 379 } \
370 } 380 }
373 383
374 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) { 384 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) {
375 return NULL; 385 return NULL;
376 } else { 386 } else {
377 *found_bind = 1; 387 *found_bind = 1;
378 return "LAZY"; 388 return (char *) "LAZY";
379 } 389 }
380} 390}
381static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 391static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
382{ 392{
383 unsigned long i; 393 unsigned long i;
384 void *symtab_void, *strtab_void; 394 void *symtab_void, *strtab_void;
385 395
386 if (!find_sym) return NULL; 396 if (!find_sym) return NULL;
387 397
398 /* debug sections */
388 symtab_void = elf_findsecbyname(elf, ".symtab"); 399 symtab_void = elf_findsecbyname(elf, ".symtab");
389 strtab_void = elf_findsecbyname(elf, ".strtab"); 400 strtab_void = elf_findsecbyname(elf, ".strtab");
401 /* fall back to runtime sections */
402 if (!symtab_void || !strtab_void) {
403 symtab_void = elf_findsecbyname(elf, ".dynsym");
404 strtab_void = elf_findsecbyname(elf, ".dynstr");
405 }
390 406
391 if (symtab_void && strtab_void) { 407 if (symtab_void && strtab_void) {
392 char *base, *basemem; 408 char *base, *basemem;
393 basemem = xstrdup(filename); 409 basemem = xstrdup(filename);
394 base = basename(basemem); 410 base = basename(basemem);
423 if (*find_sym != '*' && *found_sym) 439 if (*find_sym != '*' && *found_sym)
424 return find_sym; 440 return find_sym;
425 if (be_quiet) 441 if (be_quiet)
426 return NULL; 442 return NULL;
427 else 443 else
428 return " - "; 444 return (char *)" - ";
429} 445}
430/* scan an elf file and show all the fun stuff */ 446/* scan an elf file and show all the fun stuff */
431// #define prints(str) fputs(str, stdout) 447// #define prints(str) fputs(str, stdout)
432#define prints(str) write(fileno(stdout), str, strlen(str)) 448#define prints(str) write(fileno(stdout), str, strlen(str))
433static void scanelf_file(const char *filename) 449static void scanelf_file(const char *filename)
466 return; 482 return;
467 } 483 }
468 484
469 if (be_verbose > 1) 485 if (be_verbose > 1)
470 printf("%s: scanning file {%s,%s}\n", filename, 486 printf("%s: scanning file {%s,%s}\n", filename,
471 get_elfeitype(elf, EI_CLASS, elf->elf_class), 487 get_elfeitype(EI_CLASS, elf->elf_class),
472 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA])); 488 get_elfeitype(EI_DATA, elf->data[EI_DATA]));
473 else if (be_verbose) 489 else if (be_verbose)
474 printf("%s: scanning file\n", filename); 490 printf("%s: scanning file\n", filename);
475 491
476 /* init output buffer */ 492 /* init output buffer */
477 if (!out_buffer) { 493 if (!out_buffer) {
485 for (i = 0; out_format[i]; ++i) { 501 for (i = 0; out_format[i]; ++i) {
486 if (out_format[i] != '%') continue; 502 if (out_format[i] != '%') continue;
487 503
488 switch (out_format[++i]) { 504 switch (out_format[++i]) {
489 case '%': break; 505 case '%': break;
506 case 'F':
507 case 'p':
490 case 'F': prints("FILE "); found_file = 1; break; 508 case 'f': prints("FILE "); found_file = 1; break;
491 case 'o': prints(" TYPE "); break; 509 case 'o': prints(" TYPE "); break;
492 case 'x': prints(" PAX "); break; 510 case 'x': prints(" PAX "); break;
493 case 'e': prints("STK/REL "); break; 511 case 'e': prints("STK/REL "); break;
494 case 't': prints("TEXTREL "); break; 512 case 't': prints("TEXTREL "); break;
495 case 'r': prints("RPATH "); break; 513 case 'r': prints("RPATH "); break;
506 } 524 }
507 525
508 /* dump all the good stuff */ 526 /* dump all the good stuff */
509 for (i = 0; out_format[i]; ++i) { 527 for (i = 0; out_format[i]; ++i) {
510 const char *out; 528 const char *out;
529 const char *tmp;
511 530
512 /* make sure we trim leading spaces in quiet mode */ 531 /* make sure we trim leading spaces in quiet mode */
513 if (be_quiet && *out_buffer == ' ' && !out_buffer[1]) 532 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
514 *out_buffer = '\0'; 533 *out_buffer = '\0';
515 534
520 539
521 out = NULL; 540 out = NULL;
522 switch (out_format[++i]) { 541 switch (out_format[++i]) {
523 case '%': xchrcat(&out_buffer, '%', &out_len); break; 542 case '%': xchrcat(&out_buffer, '%', &out_len); break;
524 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break; 543 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break;
544 case 'p':
545 found_file = 1;
546 tmp = filename;
547 if (search_path) {
548 ssize_t len_search = strlen(search_path);
549 ssize_t len_file = strlen(filename);
550 if (!strncmp(filename, search_path, len_search) && \
551 len_file > len_search)
552 tmp += len_search;
553 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
554 }
555 xstrcat(&out_buffer, tmp, &out_len);
556 break;
557 case 'f':
558 found_file = 1;
559 tmp = strrchr(filename, '/');
560 tmp = (tmp == NULL ? filename : tmp+1);
561 xstrcat(&out_buffer, tmp, &out_len);
562 break;
525 case 'o': out = get_elfetype(elf); break; 563 case 'o': out = get_elfetype(elf); break;
526 case 'x': out = scanelf_file_pax(elf, &found_pax); break; 564 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
527 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break; 565 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break;
528 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 566 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
529 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 567 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
611 return 1; 649 return 1;
612 650
613 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) { 651 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
614 if ((p = strchr(path, '\n')) != NULL) 652 if ((p = strchr(path, '\n')) != NULL)
615 *p = 0; 653 *p = 0;
654 search_path = path;
616 scanelf_dir(path); 655 scanelf_dir(path);
617 } 656 }
618 if (fp != stdin) 657 if (fp != stdin)
619 fclose(fp); 658 fclose(fp);
620 return 0; 659 return 0;
720 {"help", no_argument, NULL, 'h'}, 759 {"help", no_argument, NULL, 'h'},
721 {"version", no_argument, NULL, 'V'}, 760 {"version", no_argument, NULL, 'V'},
722 {NULL, no_argument, NULL, 0x0} 761 {NULL, no_argument, NULL, 0x0}
723}; 762};
724 763
725static char *opts_help[] = { 764static const char *opts_help[] = {
726 "Scan all directories in PATH environment", 765 "Scan all directories in PATH environment",
727 "Scan all directories in /etc/ld.so.conf", 766 "Scan all directories in /etc/ld.so.conf",
728 "Scan directories recursively", 767 "Scan directories recursively",
729 "Don't recursively cross mount points", 768 "Don't recursively cross mount points",
730 "Don't scan symlinks\n", 769 "Don't scan symlinks\n",
768 807
769 puts("\nThe format modifiers for the -F option are:"); 808 puts("\nThe format modifiers for the -F option are:");
770 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO"); 809 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
771 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED"); 810 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
772 puts(" %i INTERP \t%b BIND \t%s symbol"); 811 puts(" %i INTERP \t%b BIND \t%s symbol");
812 puts(" %p filename (with search path removed)");
813 puts(" %f base filename");
773 814
774 exit(status); 815 exit(status);
775} 816}
776 817
777/* parse command line arguments and preform needed actions */ 818/* parse command line arguments and preform needed actions */
790 __FILE__, __DATE__, rcsid, argv0); 831 __FILE__, __DATE__, rcsid, argv0);
791 exit(EXIT_SUCCESS); 832 exit(EXIT_SUCCESS);
792 break; 833 break;
793 case 'h': usage(EXIT_SUCCESS); break; 834 case 'h': usage(EXIT_SUCCESS); break;
794 case 'f': 835 case 'f':
795 if (from_file == NULL) 836 if (from_file) err("Don't specify -f twice");
796 from_file = xstrdup(optarg); 837 from_file = xstrdup(optarg);
797 break; 838 break;
798 case 'o': { 839 case 'o': {
799 FILE *fp = NULL; 840 FILE *fp = NULL;
800 fp = freopen(optarg, "w", stdout); 841 if ((fp = freopen(optarg, "w", stdout)) == NULL)
801 if (fp == NULL)
802 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 842 err("Could not open output stream '%s': %s", optarg, strerror(errno));
803 stdout = fp; 843 SET_STDOUT(fp);
804 break; 844 break;
805 } 845 }
806 846
807 case 's': { 847 case 's': {
808 size_t len; 848 size_t len;
849 if (find_sym) err("Don't specify -s twice");
809 find_sym = xstrdup(optarg); 850 find_sym = xstrdup(optarg);
810 len = strlen(find_sym) + 1; 851 len = strlen(find_sym) + 1;
811 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1)); 852 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1));
812 sprintf(versioned_symname, "%s@", find_sym); 853 sprintf(versioned_symname, "%s@", find_sym);
813 break; 854 break;
814 } 855 }
815 856
816 case 'F': { 857 case 'F': {
817 if (!out_format) 858 if (out_format) err("Don't specify -F twice");
818 out_format = xstrdup(optarg); 859 out_format = xstrdup(optarg);
819 break; 860 break;
820 } 861 }
821 862
822 case 'y': scan_symlink = 0; break; 863 case 'y': scan_symlink = 0; break;
823 case 'B': show_banner = 0; break; 864 case 'B': show_banner = 0; break;
854 if (out_format[i] != '%') continue; 895 if (out_format[i] != '%') continue;
855 896
856 switch (out_format[++i]) { 897 switch (out_format[++i]) {
857 case '%': break; 898 case '%': break;
858 case 'F': break; 899 case 'F': break;
900 case 'p': break;
901 case 'f': break;
859 case 's': break; 902 case 's': break;
860 case 'o': break; 903 case 'o': break;
861 case 'x': show_pax = 1; break; 904 case 'x': show_pax = 1; break;
862 case 'e': show_stack = 1; break; 905 case 'e': show_stack = 1; break;
863 case 't': show_textrel = 1; break; 906 case 't': show_textrel = 1; break;
898 free(from_file); 941 free(from_file);
899 from_file = *argv; 942 from_file = *argv;
900 } 943 }
901 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file) 944 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
902 err("Nothing to scan !?"); 945 err("Nothing to scan !?");
903 while (optind < argc) 946 while (optind < argc) {
904 scanelf_dir(argv[optind++]); 947 search_path = argv[optind++];
948 scanelf_dir(search_path);
949 }
905 950
906 /* clean up */ 951 /* clean up */
907 if (find_sym) { 952 if (find_sym) {
908 free(find_sym); 953 free(find_sym);
909 free(versioned_symname); 954 free(versioned_symname);
930 return ret; 975 return ret;
931} 976}
932 977
933static void xstrcat(char **dst, const char *src, size_t *curr_len) 978static void xstrcat(char **dst, const char *src, size_t *curr_len)
934{ 979{
935 long new_len; 980 size_t new_len;
936 981
937 new_len = strlen(*dst) + strlen(src); 982 new_len = strlen(*dst) + strlen(src);
938 if (*curr_len <= new_len) { 983 if (*curr_len <= new_len) {
939 *curr_len = new_len + (*curr_len / 2); 984 *curr_len = new_len + (*curr_len / 2);
940 *dst = realloc(*dst, *curr_len); 985 *dst = realloc(*dst, *curr_len);
959 if (argc < 2) 1004 if (argc < 2)
960 usage(EXIT_FAILURE); 1005 usage(EXIT_FAILURE);
961 parseargs(argc, argv); 1006 parseargs(argc, argv);
962 fclose(stdout); 1007 fclose(stdout);
963#ifdef __BOUNDS_CHECKING_ON 1008#ifdef __BOUNDS_CHECKING_ON
964 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()"); 1009 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()");
965#endif 1010#endif
966 return EXIT_SUCCESS; 1011 return EXIT_SUCCESS;
967} 1012}

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.69

  ViewVC Help
Powered by ViewVC 1.1.20