/[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.48 Revision 1.49
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org> 2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 3 * Copyright 1999-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 4 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.48 2005/05/18 02:51:02 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.49 2005/05/18 04:08:30 vapier Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
33#include <getopt.h> 33#include <getopt.h>
34#include <assert.h> 34#include <assert.h>
35 35
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.48 2005/05/18 02:51:02 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.49 2005/05/18 04:08:30 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
64static char show_stack = 0; 64static char show_stack = 0;
65static char show_textrel = 0; 65static char show_textrel = 0;
66static char show_rpath = 0; 66static char show_rpath = 0;
67static char show_needed = 0; 67static char show_needed = 0;
68static char show_interp = 0; 68static char show_interp = 0;
69static char show_bind = 0;
69static char show_banner = 1; 70static char show_banner = 1;
70static char be_quiet = 0; 71static char be_quiet = 0;
71static char be_verbose = 0; 72static char be_verbose = 0;
72static char *find_sym = NULL, *versioned_symname = NULL; 73static char *find_sym = NULL, *versioned_symname = NULL;
73static char *out_format = NULL; 74static char *out_format = NULL;
266 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 267 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
267 dyn = DYN ## B (elf->data + offset); \ 268 dyn = DYN ## B (elf->data + offset); \
268 while (EGET(dyn->d_tag) != DT_NULL) { \ 269 while (EGET(dyn->d_tag) != DT_NULL) { \
269 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 270 if (EGET(dyn->d_tag) == DT_NEEDED) { \
270 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 271 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
271 if (offset >= elf->len) continue; \ 272 if (offset >= elf->len) { \
273 ++dyn; \
274 continue; \
275 } \
272 needed = (char*)(elf->data + offset); \ 276 needed = (char*)(elf->data + offset); \
273 if (*found_needed) xchrcat(ret, ',', ret_len); \ 277 if (*found_needed) xchrcat(ret, ',', ret_len); \
274 xstrcat(ret, needed, ret_len); \ 278 xstrcat(ret, needed, ret_len); \
275 *found_needed = 1; \ 279 *found_needed = 1; \
276 } \ 280 } \
298 } 302 }
299 SHOW_INTERP(32) 303 SHOW_INTERP(32)
300 SHOW_INTERP(64) 304 SHOW_INTERP(64)
301 } 305 }
302 return NULL; 306 return NULL;
307}
308static char *scanelf_file_bind(elfobj *elf, char *found_bind)
309{
310 unsigned long i;
311 struct stat s;
312
313 if (!show_bind) return NULL;
314
315#define SHOW_BIND(B) \
316 if (elf->elf_class == ELFCLASS ## B) { \
317 Elf ## B ## _Dyn *dyn; \
318 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
319 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
320 Elf ## B ## _Off offset; \
321 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
322 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
323 offset = EGET(phdr[i].p_offset); \
324 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
325 dyn = DYN ## B (elf->data + offset); \
326 while (EGET(dyn->d_tag) != DT_NULL) { \
327 if (EGET(dyn->d_tag) == DT_BIND_NOW || \
328 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \
329 { \
330 if (be_quiet) return NULL; \
331 *found_bind = 1; \
332 return "NOW"; \
333 } \
334 ++dyn; \
335 } \
336 } \
337 }
338 SHOW_BIND(32)
339 SHOW_BIND(64)
340
341 fstat(elf->fd, &s);
342 if (be_quiet && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) {
343 return NULL;
344 } else {
345 *found_bind = 1;
346 return "LAZY";
347 }
303} 348}
304static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 349static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
305{ 350{
306 unsigned long i; 351 unsigned long i;
307 void *symtab_void, *strtab_void; 352 void *symtab_void, *strtab_void;
350#define prints(str) fputs(str, stdout) 395#define prints(str) fputs(str, stdout)
351static void scanelf_file(const char *filename) 396static void scanelf_file(const char *filename)
352{ 397{
353 unsigned long i; 398 unsigned long i;
354 char found_pax, found_stack, found_relro, found_textrel, 399 char found_pax, found_stack, found_relro, found_textrel,
355 found_rpath, found_needed, found_interp, found_sym, 400 found_rpath, found_needed, found_interp, found_bind,
356 found_file; 401 found_sym, found_file;
357 elfobj *elf; 402 elfobj *elf;
358 struct stat st; 403 struct stat st;
359 static char *out_buffer = NULL; 404 static char *out_buffer = NULL;
360 static size_t out_len; 405 static size_t out_len;
361 406
369 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 414 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
370 return; 415 return;
371 } 416 }
372 417
373 found_pax = found_stack = found_relro = found_textrel = \ 418 found_pax = found_stack = found_relro = found_textrel = \
374 found_rpath = found_needed = found_interp = found_sym = \ 419 found_rpath = found_needed = found_interp = found_bind = \
375 found_file = 0; 420 found_sym = found_file = 0;
376 421
377 /* verify this is real ELF */ 422 /* verify this is real ELF */
378 if ((elf = readelf(filename)) == NULL) { 423 if ((elf = readelf(filename)) == NULL) {
379 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 424 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
380 return; 425 return;
394 } 439 }
395 *out_buffer = '\0'; 440 *out_buffer = '\0';
396 441
397 /* show the header */ 442 /* show the header */
398 if (!be_quiet && show_banner) { 443 if (!be_quiet && show_banner) {
399 for (i=0; out_format[i]; ++i) { 444 for (i = 0; out_format[i]; ++i) {
400 if (out_format[i] != '%') continue; 445 if (out_format[i] != '%') continue;
401 446
402 switch (out_format[++i]) { 447 switch (out_format[++i]) {
403 case '%': break; 448 case '%': break;
404 case 'F': prints("FILE "); break; 449 case 'F': prints("FILE "); found_file = 1; break;
405 case 'o': prints(" TYPE "); break; 450 case 'o': prints(" TYPE "); break;
406 case 'x': prints(" PAX "); break; 451 case 'x': prints(" PAX "); break;
407 case 'e': prints("STK/REL "); break; 452 case 'e': prints("STK/REL "); break;
408 case 't': prints("TEXTREL "); break; 453 case 't': prints("TEXTREL "); break;
409 case 'r': prints("RPATH "); break; 454 case 'r': prints("RPATH "); break;
410 case 'n': prints("NEEDED "); break; 455 case 'n': prints("NEEDED "); break;
411 case 'i': prints("INTERP "); break; 456 case 'i': prints("INTERP "); break;
457 case 'b': prints("BIND "); break;
412 case 's': prints("SYM "); break; 458 case 's': prints("SYM "); break;
413 } 459 }
414 } 460 }
461 if (!found_file) prints("FILE ");
415 prints("\n"); 462 prints("\n");
463 found_file = 0;
416 show_banner = 0; 464 show_banner = 0;
417 } 465 }
418 466
419 /* dump all the good stuff */ 467 /* dump all the good stuff */
420 for (i=0; out_format[i]; ++i) { 468 for (i = 0; out_format[i]; ++i) {
421 const char *out; 469 const char *out;
422 470
423 /* make sure we trim leading spaces in quiet mode */ 471 /* make sure we trim leading spaces in quiet mode */
424 if (be_quiet && *out_buffer == ' ' && !out_buffer[1]) 472 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
425 *out_buffer = '\0'; 473 *out_buffer = '\0';
438 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break; 486 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break;
439 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 487 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
440 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 488 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
441 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break; 489 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break;
442 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 490 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
491 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
443 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break; 492 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break;
444 } 493 }
445 if (out) xstrcat(&out_buffer, out, &out_len); 494 if (out) xstrcat(&out_buffer, out, &out_len);
446 } 495 }
447 496
448 if (!found_file) { 497 if (!found_file) {
449 if (!be_quiet || found_pax || found_stack || found_textrel || \ 498 if (!be_quiet || found_pax || found_stack || found_textrel || \
450 found_rpath || found_needed || found_interp || found_sym) 499 found_rpath || found_needed || found_interp || found_bind || \
500 found_sym)
501 {
502 xchrcat(&out_buffer, ' ', &out_len);
451 xstrcat(&out_buffer, filename, &out_len); 503 xstrcat(&out_buffer, filename, &out_len);
504 }
452 } 505 }
453 if (!(be_quiet && xemptybuffer(out_buffer))) 506 if (!(be_quiet && xemptybuffer(out_buffer)))
454 puts(out_buffer); 507 puts(out_buffer);
455 508
456 unreadelf(elf); 509 unreadelf(elf);
599} 652}
600 653
601 654
602 655
603/* usage / invocation handling functions */ 656/* usage / invocation handling functions */
604#define PARSE_FLAGS "plRmyxetrnis:aqvF:f:o:BhV" 657#define PARSE_FLAGS "plRmyxetrnibs:aqvF:f:o:BhV"
605#define a_argument required_argument 658#define a_argument required_argument
606static struct option const long_opts[] = { 659static struct option const long_opts[] = {
607 {"path", no_argument, NULL, 'p'}, 660 {"path", no_argument, NULL, 'p'},
608 {"ldpath", no_argument, NULL, 'l'}, 661 {"ldpath", no_argument, NULL, 'l'},
609 {"recursive", no_argument, NULL, 'R'}, 662 {"recursive", no_argument, NULL, 'R'},
613 {"header", no_argument, NULL, 'e'}, 666 {"header", no_argument, NULL, 'e'},
614 {"textrel", no_argument, NULL, 't'}, 667 {"textrel", no_argument, NULL, 't'},
615 {"rpath", no_argument, NULL, 'r'}, 668 {"rpath", no_argument, NULL, 'r'},
616 {"needed", no_argument, NULL, 'n'}, 669 {"needed", no_argument, NULL, 'n'},
617 {"interp", no_argument, NULL, 'i'}, 670 {"interp", no_argument, NULL, 'i'},
671 {"bind", no_argument, NULL, 'b'},
618 {"symbol", a_argument, NULL, 's'}, 672 {"symbol", a_argument, NULL, 's'},
619 {"all", no_argument, NULL, 'a'}, 673 {"all", no_argument, NULL, 'a'},
620 {"quiet", no_argument, NULL, 'q'}, 674 {"quiet", no_argument, NULL, 'q'},
621 {"verbose", no_argument, NULL, 'v'}, 675 {"verbose", no_argument, NULL, 'v'},
622 {"format", a_argument, NULL, 'F'}, 676 {"format", a_argument, NULL, 'F'},
637 "Print GNU_STACK markings", 691 "Print GNU_STACK markings",
638 "Print TEXTREL information", 692 "Print TEXTREL information",
639 "Print RPATH information", 693 "Print RPATH information",
640 "Print NEEDED information", 694 "Print NEEDED information",
641 "Print INTERP information", 695 "Print INTERP information",
696 "Print BIND information",
642 "Find a specified symbol", 697 "Find a specified symbol",
643 "Print all scanned info (-x -e -t -r -n -i)\n", 698 "Print all scanned info (-x -e -t -r -n -i)\n",
644 "Only output 'bad' things", 699 "Only output 'bad' things",
645 "Be verbose (can be specified more than once)", 700 "Be verbose (can be specified more than once)",
646 "Use specified format for output", 701 "Use specified format for output",
671 exit(status); 726 exit(status);
672 727
673 puts("\nThe format modifiers for the -F option are:"); 728 puts("\nThe format modifiers for the -F option are:");
674 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO"); 729 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
675 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED"); 730 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
676 puts(" %i INTERP \t%s symbol"); 731 puts(" %i INTERP \t%b BIND \t%s symbol");
677 732
678 exit(status); 733 exit(status);
679} 734}
680 735
681/* parse command line arguments and preform needed actions */ 736/* parse command line arguments and preform needed actions */
732 case 'e': show_stack = 1; break; 787 case 'e': show_stack = 1; break;
733 case 't': show_textrel = 1; break; 788 case 't': show_textrel = 1; break;
734 case 'r': show_rpath = 1; break; 789 case 'r': show_rpath = 1; break;
735 case 'n': show_needed = 1; break; 790 case 'n': show_needed = 1; break;
736 case 'i': show_interp = 1; break; 791 case 'i': show_interp = 1; break;
792 case 'b': show_bind = 1; break;
737 case 'q': be_quiet = 1; break; 793 case 'q': be_quiet = 1; break;
738 case 'v': be_verbose = (be_verbose % 20) + 1; break; 794 case 'v': be_verbose = (be_verbose % 20) + 1; break;
739 case 'a': show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 1; break; 795 case 'a': show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 1; break;
740 796
741 case ':': 797 case ':':
742 warn("Option missing parameter\n"); 798 err("Option missing parameter\n");
743 usage(EXIT_FAILURE);
744 break;
745 case '?': 799 case '?':
746 warn("Unknown option\n"); 800 err("Unknown option\n");
747 usage(EXIT_FAILURE);
748 break;
749 default: 801 default:
750 err("Unhandled option '%c'", i); 802 err("Unhandled option '%c'", i);
751 break;
752 }
753 } 803 }
754 804 }
755 if (be_quiet && be_verbose)
756 err("You can be quiet or you can be verbose, not both, stupid");
757 805
758 /* let the format option override all other options */ 806 /* let the format option override all other options */
759 if (out_format) { 807 if (out_format) {
760 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 808 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0;
761 for (i = 0; out_format[i]; ++i) { 809 for (i = 0; out_format[i]; ++i) {
770 case 'e': show_stack = 1; break; 818 case 'e': show_stack = 1; break;
771 case 't': show_textrel = 1; break; 819 case 't': show_textrel = 1; break;
772 case 'r': show_rpath = 1; break; 820 case 'r': show_rpath = 1; break;
773 case 'n': show_needed = 1; break; 821 case 'n': show_needed = 1; break;
774 case 'i': show_interp = 1; break; 822 case 'i': show_interp = 1; break;
823 case 'b': show_bind = 1; break;
775 default: 824 default:
776 err("Invalid format specifier '%c' (byte %i)", 825 err("Invalid format specifier '%c' (byte %i)",
777 out_format[i], i+1); 826 out_format[i], i+1);
778 } 827 }
779 } 828 }
787 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len); 836 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len);
788 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 837 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
789 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 838 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
790 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 839 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
791 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 840 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
841 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
792 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len); 842 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
793 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 843 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
794 } 844 }
795 if (be_verbose > 2) printf("Format: %s\n", out_format); 845 if (be_verbose > 2) printf("Format: %s\n", out_format);
796 846
856 xstrcat(dst, my_app, curr_len); 906 xstrcat(dst, my_app, curr_len);
857} 907}
858static int xemptybuffer(const char *buff) 908static int xemptybuffer(const char *buff)
859{ 909{
860 long i; 910 long i;
861 for (i=0; buff[i]; ++i) 911 for (i = 0; buff[i]; ++i)
862 if (buff[i] != ' ') 912 if (buff[i] != ' ')
863 return 0; 913 return 0;
864 return 1; 914 return 1;
865} 915}
866 916

Legend:
Removed from v.1.48  
changed lines
  Added in v.1.49

  ViewVC Help
Powered by ViewVC 1.1.20