/[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.83 Revision 1.84
1/* 1/*
2 * Copyright 2003-2005 Gentoo Foundation 2 * Copyright 2003-2005 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.83 2005/06/22 17:43:12 solar Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.84 2005/07/22 00:10:51 vapier Exp $
5 * 5 *
6 ******************************************************************** 6 ********************************************************************
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * 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
9 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
33#include <dirent.h> 33#include <dirent.h>
34#include <getopt.h> 34#include <getopt.h>
35#include <assert.h> 35#include <assert.h>
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.83 2005/06/22 17:43:12 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.84 2005/07/22 00:10:51 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41#define IS_MODIFIER(c) (c == '%' || c == '#') 41#define IS_MODIFIER(c) (c == '%' || c == '#')
42 42
43 43
66static char show_textrel = 0; 66static char show_textrel = 0;
67static char show_rpath = 0; 67static char show_rpath = 0;
68static char show_needed = 0; 68static char show_needed = 0;
69static char show_interp = 0; 69static char show_interp = 0;
70static char show_bind = 0; 70static char show_bind = 0;
71static char show_soname = 0;
71static char show_textrels = 0; 72static char show_textrels = 0;
72static char show_banner = 1; 73static char show_banner = 1;
73static char be_quiet = 0; 74static char be_quiet = 0;
74static char be_verbose = 0; 75static char be_verbose = 0;
75static char be_wewy_wewy_quiet = 0; 76static char be_wewy_wewy_quiet = 0;
348} 349}
349 350
350static void rpath_security_checks(elfobj *, char *); 351static void rpath_security_checks(elfobj *, char *);
351static void rpath_security_checks(elfobj *elf, char *item) { 352static void rpath_security_checks(elfobj *elf, char *item) {
352 struct stat st; 353 struct stat st;
353 switch(*item) { 354 switch (*item) {
354 case 0: 355 case 0:
355 warnf("Security problem NULL RPATH in %s", elf->filename); 356 warnf("Security problem NULL RPATH in %s", elf->filename);
356 break; 357 break;
357 case '/': break; 358 case '/': break;
358 case '$': 359 case '$':
359 if (fstat(elf->fd, &st) != (-1)) 360 if (fstat(elf->fd, &st) != -1)
360 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID)) 361 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID))
361 warnf("Security problem with RPATH='%s' in %s with mode set of %o", 362 warnf("Security problem with RPATH='%s' in %s with mode set of %o",
362 item, elf->filename, st.st_mode & 07777); 363 item, elf->filename, st.st_mode & 07777);
363 break; 364 break;
364 default: 365 default:
365 warnf("Maybe? sec problem with RPATH='%s' in %s", item, elf->filename); 366 warnf("Maybe? sec problem with RPATH='%s' in %s", item, elf->filename);
366 break; 367 break;
367 } 368 }
368} 369}
369
370static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 370static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
371{ 371{
372 unsigned long i, s; 372 unsigned long i, s;
373 char *rpath, *runpath, **r; 373 char *rpath, *runpath, **r;
374 void *strtbl_void; 374 void *strtbl_void;
458 } else if (rpath || runpath) 458 } else if (rpath || runpath)
459 xstrcat(ret, (runpath ? runpath : rpath), ret_len); 459 xstrcat(ret, (runpath ? runpath : rpath), ret_len);
460 else if (!be_quiet) 460 else if (!be_quiet)
461 xstrcat(ret, " - ", ret_len); 461 xstrcat(ret, " - ", ret_len);
462} 462}
463static char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len) 463static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len)
464{ 464{
465 unsigned long i; 465 unsigned long i;
466 char *needed; 466 char *needed;
467 void *strtbl_void; 467 void *strtbl_void;
468 468
507 ++dyn; \ 507 ++dyn; \
508 } \ 508 } \
509 } } 509 } }
510 SHOW_NEEDED(32) 510 SHOW_NEEDED(32)
511 SHOW_NEEDED(64) 511 SHOW_NEEDED(64)
512#if 0
513 if (op == 0 && !*found_needed)
514 warn("ELF lacks DT_NEEDED sections: %s", elf->filename);
515#endif
512 } 516 }
513 517
514 return NULL; 518 return NULL;
515} 519}
516static char *scanelf_file_interp(elfobj *elf, char *found_interp) 520static char *scanelf_file_interp(elfobj *elf, char *found_interp)
573 return NULL; 577 return NULL;
574 } else { 578 } else {
575 *found_bind = 1; 579 *found_bind = 1;
576 return (char *) "LAZY"; 580 return (char *) "LAZY";
577 } 581 }
582}
583static char *scanelf_file_soname(elfobj *elf, char *found_soname)
584{
585 unsigned long i;
586 char *soname;
587 void *strtbl_void;
588
589 if (!show_soname) return NULL;
590
591 strtbl_void = elf_findsecbyname(elf, ".dynstr");
592
593 if (elf->phdr && strtbl_void) {
594#define SHOW_SONAME(B) \
595 if (elf->elf_class == ELFCLASS ## B) { \
596 Elf ## B ## _Dyn *dyn; \
597 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
598 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
599 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
600 Elf ## B ## _Off offset; \
601 /* only look for soname in shared objects */ \
602 if (ehdr->e_type != ET_DYN) \
603 return NULL; \
604 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
605 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
606 offset = EGET(phdr[i].p_offset); \
607 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
608 dyn = DYN ## B (elf->data + offset); \
609 while (EGET(dyn->d_tag) != DT_NULL) { \
610 if (EGET(dyn->d_tag) == DT_SONAME) { \
611 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
612 if (offset >= (Elf ## B ## _Off)elf->len) { \
613 ++dyn; \
614 continue; \
615 } \
616 soname = (char*)(elf->data + offset); \
617 *found_soname = 1; \
618 return (be_wewy_wewy_quiet ? NULL : soname); \
619 } \
620 ++dyn; \
621 } \
622 } }
623 SHOW_SONAME(32)
624 SHOW_SONAME(64)
625 }
626
627 return NULL;
578} 628}
579static char *scanelf_file_sym(elfobj *elf, char *found_sym) 629static char *scanelf_file_sym(elfobj *elf, char *found_sym)
580{ 630{
581 unsigned long i; 631 unsigned long i;
582 void *symtab_void, *strtab_void; 632 void *symtab_void, *strtab_void;
627#define prints(str) write(fileno(stdout), str, strlen(str)) 677#define prints(str) write(fileno(stdout), str, strlen(str))
628static void scanelf_file(const char *filename) 678static void scanelf_file(const char *filename)
629{ 679{
630 unsigned long i; 680 unsigned long i;
631 char found_pax, found_phdr, found_relro, found_load, found_textrel, 681 char found_pax, found_phdr, found_relro, found_load, found_textrel,
632 found_rpath, found_needed, found_interp, found_bind, 682 found_rpath, found_needed, found_interp, found_bind, found_soname,
633 found_sym, found_lib, found_file, found_textrels; 683 found_sym, found_lib, found_file, found_textrels;
634 elfobj *elf; 684 elfobj *elf;
635 struct stat st; 685 struct stat st;
636 static char *out_buffer = NULL; 686 static char *out_buffer = NULL;
637 static size_t out_len; 687 static size_t out_len;
650 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 700 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
651 return; 701 return;
652 } 702 }
653 703
654 found_pax = found_phdr = found_relro = found_load = found_textrel = \ 704 found_pax = found_phdr = found_relro = found_load = found_textrel = \
655 found_rpath = found_needed = found_interp = found_bind = \ 705 found_rpath = found_needed = found_interp = found_bind = found_soname = \
656 found_sym = found_lib = found_file = found_textrels = 0; 706 found_sym = found_lib = found_file = found_textrels = 0;
657 707
658 /* verify this is real ELF */ 708 /* verify this is real ELF */
659 if ((elf = readelf(filename)) == NULL) { 709 if ((elf = readelf(filename)) == NULL) {
660 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 710 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
692 case 't': prints("TEXTREL "); break; 742 case 't': prints("TEXTREL "); break;
693 case 'r': prints("RPATH "); break; 743 case 'r': prints("RPATH "); break;
694 case 'n': prints("NEEDED "); break; 744 case 'n': prints("NEEDED "); break;
695 case 'i': prints("INTERP "); break; 745 case 'i': prints("INTERP "); break;
696 case 'b': prints("BIND "); break; 746 case 'b': prints("BIND "); break;
747 case 'S': prints("SONAME "); break;
697 case 's': prints("SYM "); break; 748 case 's': prints("SYM "); break;
698 case 'N': prints("LIB "); break; 749 case 'N': prints("LIB "); break;
699 case 'T': prints("TEXTRELS "); break; 750 case 'T': prints("TEXTRELS "); break;
700 default: warnf("'%c' has no title ?", out_format[i]); 751 default: warnf("'%c' has no title ?", out_format[i]);
701 } 752 }
760 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 811 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
761 case 'n': 812 case 'n':
762 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break; 813 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
763 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 814 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
764 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 815 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
816 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
765 case 's': out = scanelf_file_sym(elf, &found_sym); break; 817 case 's': out = scanelf_file_sym(elf, &found_sym); break;
766 default: warnf("'%c' has no scan code?", out_format[i]); 818 default: warnf("'%c' has no scan code?", out_format[i]);
767 } 819 }
768 if (out) xstrcat(&out_buffer, out, &out_len); 820 if (out) xstrcat(&out_buffer, out, &out_len);
769 } 821 }
770 822
771#define FOUND_SOMETHING() \ 823#define FOUND_SOMETHING() \
772 (found_pax || found_phdr || found_relro || found_load || found_textrel || \ 824 (found_pax || found_phdr || found_relro || found_load || found_textrel || \
773 found_rpath || found_needed || found_interp || found_bind || \ 825 found_rpath || found_needed || found_interp || found_bind || \
774 found_sym || found_lib || found_textrels) 826 found_soname || found_sym || found_lib || found_textrels)
775 827
776 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) { 828 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
777 xchrcat(&out_buffer, ' ', &out_len); 829 xchrcat(&out_buffer, ' ', &out_len);
778 xstrcat(&out_buffer, filename, &out_len); 830 xstrcat(&out_buffer, filename, &out_len);
779 } 831 }
930} 982}
931 983
932 984
933 985
934/* usage / invocation handling functions */ 986/* usage / invocation handling functions */
935#define PARSE_FLAGS "plRmyxetrnibs:N:TaqvF:f:o:BhV" 987#define PARSE_FLAGS "plRmyxetrnibSs:N:TaqvF:f:o:BhV"
936#define a_argument required_argument 988#define a_argument required_argument
937static struct option const long_opts[] = { 989static struct option const long_opts[] = {
938 {"path", no_argument, NULL, 'p'}, 990 {"path", no_argument, NULL, 'p'},
939 {"ldpath", no_argument, NULL, 'l'}, 991 {"ldpath", no_argument, NULL, 'l'},
940 {"recursive", no_argument, NULL, 'R'}, 992 {"recursive", no_argument, NULL, 'R'},
945 {"textrel", no_argument, NULL, 't'}, 997 {"textrel", no_argument, NULL, 't'},
946 {"rpath", no_argument, NULL, 'r'}, 998 {"rpath", no_argument, NULL, 'r'},
947 {"needed", no_argument, NULL, 'n'}, 999 {"needed", no_argument, NULL, 'n'},
948 {"interp", no_argument, NULL, 'i'}, 1000 {"interp", no_argument, NULL, 'i'},
949 {"bind", no_argument, NULL, 'b'}, 1001 {"bind", no_argument, NULL, 'b'},
1002 {"soname", no_argument, NULL, 'S'},
950 {"symbol", a_argument, NULL, 's'}, 1003 {"symbol", a_argument, NULL, 's'},
951 {"lib", a_argument, NULL, 'N'}, 1004 {"lib", a_argument, NULL, 'N'},
952 {"textrels", no_argument, NULL, 'T'}, 1005 {"textrels", no_argument, NULL, 'T'},
953 {"all", no_argument, NULL, 'a'}, 1006 {"all", no_argument, NULL, 'a'},
954 {"quiet", no_argument, NULL, 'q'}, 1007 {"quiet", no_argument, NULL, 'q'},
973 "Print TEXTREL information", 1026 "Print TEXTREL information",
974 "Print RPATH information", 1027 "Print RPATH information",
975 "Print NEEDED information", 1028 "Print NEEDED information",
976 "Print INTERP information", 1029 "Print INTERP information",
977 "Print BIND information", 1030 "Print BIND information",
1031 "Print SONAME information",
978 "Find a specified symbol", 1032 "Find a specified symbol",
979 "Find a specified library", 1033 "Find a specified library",
980 "Locate cause of TEXTREL", 1034 "Locate cause of TEXTREL",
981 "Print all scanned info (-x -e -t -r -b)\n", 1035 "Print all scanned info (-x -e -t -r -b)\n",
982 "Only output 'bad' things", 1036 "Only output 'bad' things",
1081 case 't': show_textrel = 1; break; 1135 case 't': show_textrel = 1; break;
1082 case 'r': show_rpath = 1; break; 1136 case 'r': show_rpath = 1; break;
1083 case 'n': show_needed = 1; break; 1137 case 'n': show_needed = 1; break;
1084 case 'i': show_interp = 1; break; 1138 case 'i': show_interp = 1; break;
1085 case 'b': show_bind = 1; break; 1139 case 'b': show_bind = 1; break;
1140 case 'S': show_soname = 1; break;
1086 case 'T': show_textrels = 1; break; 1141 case 'T': show_textrels = 1; break;
1087 case 'q': be_quiet = 1; break; 1142 case 'q': be_quiet = 1; break;
1088 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1143 case 'v': be_verbose = (be_verbose % 20) + 1; break;
1089 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break; 1144 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break;
1090 1145
1098 } 1153 }
1099 1154
1100 /* let the format option override all other options */ 1155 /* let the format option override all other options */
1101 if (out_format) { 1156 if (out_format) {
1102 show_pax = show_phdr = show_textrel = show_rpath = \ 1157 show_pax = show_phdr = show_textrel = show_rpath = \
1103 show_needed = show_interp = show_bind = show_textrels = 0; 1158 show_needed = show_interp = show_bind = show_soname = \
1159 show_textrels = 0;
1104 for (i = 0; out_format[i]; ++i) { 1160 for (i = 0; out_format[i]; ++i) {
1105 if (!IS_MODIFIER(out_format[i])) continue; 1161 if (!IS_MODIFIER(out_format[i])) continue;
1106 1162
1107 switch (out_format[++i]) { 1163 switch (out_format[++i]) {
1108 case '%': break; 1164 case '%': break;
1118 case 't': show_textrel = 1; break; 1174 case 't': show_textrel = 1; break;
1119 case 'r': show_rpath = 1; break; 1175 case 'r': show_rpath = 1; break;
1120 case 'n': show_needed = 1; break; 1176 case 'n': show_needed = 1; break;
1121 case 'i': show_interp = 1; break; 1177 case 'i': show_interp = 1; break;
1122 case 'b': show_bind = 1; break; 1178 case 'b': show_bind = 1; break;
1179 case 'S': show_soname = 1; break;
1123 case 'T': show_textrels = 1; break; 1180 case 'T': show_textrels = 1; break;
1124 default: 1181 default:
1125 err("Invalid format specifier '%c' (byte %i)", 1182 err("Invalid format specifier '%c' (byte %i)",
1126 out_format[i], i+1); 1183 out_format[i], i+1);
1127 } 1184 }
1137 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 1194 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
1138 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 1195 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
1139 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 1196 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
1140 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 1197 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
1141 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len); 1198 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
1199 if (show_soname) xstrcat(&out_format, "%S ", &fmt_len);
1142 if (show_textrels) xstrcat(&out_format, "%T ", &fmt_len); 1200 if (show_textrels) xstrcat(&out_format, "%T ", &fmt_len);
1143 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len); 1201 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
1144 if (find_lib) xstrcat(&out_format, "%N ", &fmt_len); 1202 if (find_lib) xstrcat(&out_format, "%N ", &fmt_len);
1145 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 1203 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
1146 } 1204 }

Legend:
Removed from v.1.83  
changed lines
  Added in v.1.84

  ViewVC Help
Powered by ViewVC 1.1.20