/[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.26 Revision 1.32
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/Attic/scanelf.c,v 1.26 2005/04/05 00:51:33 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.32 2005/04/07 00:01:40 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
22 */ 22 */
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#define __USE_GNU
27#include <string.h> 28#include <string.h>
28#include <errno.h> 29#include <errno.h>
29#include <unistd.h> 30#include <unistd.h>
30#include <sys/stat.h> 31#include <sys/stat.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <getopt.h> 33#include <getopt.h>
33#include <assert.h> 34#include <assert.h>
34 35
35#include "paxelf.h" 36#include "paxelf.h"
36 37
37static const char *rcsid = "$Id: scanelf.c,v 1.26 2005/04/05 00:51:33 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.32 2005/04/07 00:01:40 vapier Exp $";
38 39
39 40
40/* helper functions for showing errors */ 41/* helper functions for showing errors */
41#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/ 42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
42#define warn(fmt, args...) \ 43#define warn(fmt, args...) \
65static char dir_crossmount = 1; 66static char dir_crossmount = 1;
66static char show_pax = 0; 67static char show_pax = 0;
67static char show_stack = 0; 68static char show_stack = 0;
68static char show_textrel = 0; 69static char show_textrel = 0;
69static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
70static char show_banner = 1; 72static char show_banner = 1;
71static char be_quiet = 0; 73static char be_quiet = 0;
72static char be_verbose = 0; 74static char be_verbose = 0;
75static char *find_sym = NULL;
73 76
74 77
75 78
76/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
77static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
78{ 81{
79 int i; 82 int i;
80 char found_pax, found_stack, found_relro, found_textrel, found_rpath; 83 char found_pax, found_stack, found_relro, found_textrel,
84 found_rpath, found_needed, found_sym;
81 elfobj *elf; 85 elfobj *elf;
82 86
83 found_pax = found_stack = found_relro = found_textrel = found_rpath = 0; 87 found_pax = found_stack = found_relro = found_textrel = \
88 found_rpath = found_needed = found_sym = 0;
84 89
85 /* verify this is real ELF */ 90 /* verify this is real ELF */
86 if ((elf = readelf(filename)) == NULL) { 91 if ((elf = readelf(filename)) == NULL) {
87 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 92 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
88 return; 93 return;
95 else if (be_verbose) 100 else if (be_verbose)
96 printf("%s: scanning file\n", filename); 101 printf("%s: scanning file\n", filename);
97 102
98 /* show the header */ 103 /* show the header */
99 if (!be_quiet && show_banner) { 104 if (!be_quiet && show_banner) {
100 printf(" TYPE "); 105 printf(" TYPE ");
101 if (show_pax) printf(" PAX "); 106 if (show_pax) printf(" PAX ");
102 if (show_stack) printf(" STK/REL "); 107 if (show_stack) printf("STK/REL ");
103 if (show_textrel) printf("TEXTREL "); 108 if (show_textrel) printf("TEXTREL ");
104 if (show_rpath) printf("RPATH "); 109 if (show_rpath) printf("RPATH ");
110 if (show_needed) printf("NEEDED ");
105 printf(" FILE\n"); 111 printf(" FILE\n");
106 show_banner = 0; 112 show_banner = 0;
107 } 113 }
108 114
109 /* dump all the good stuff */ 115 /* dump all the good stuff */
208 printf("%-5s ", (runpath ? runpath : rpath)); 214 printf("%-5s ", (runpath ? runpath : rpath));
209 else if (!be_quiet && !found_rpath) 215 else if (!be_quiet && !found_rpath)
210 printf(" - "); 216 printf(" - ");
211 } 217 }
212 218
219 /* print out all the NEEDED entries */
220 if (show_needed) {
221 char *needed;
222 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
223
224 if (strtbl_void) {
225#define SHOW_NEEDED(B) \
226 if (elf->elf_class == ELFCLASS ## B) { \
227 Elf ## B ## _Dyn *dyn; \
228 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
229 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
231 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
232 if (be_verbose && EGET(phdr[i].p_type) == PT_INTERP) { \
233 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
234 printf("%s\n", elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr)); \
235 exit(0); \
236 } \
237 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
238 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
239 while (EGET(dyn->d_tag) != DT_NULL) { \
240 if (EGET(dyn->d_tag) == DT_NEEDED) { \
241 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
242 if (found_needed) printf(","); \
243 printf("%s", needed); \
244 found_needed = 1; \
245 } \
246 ++dyn; \
247 } \
248 } }
249 SHOW_NEEDED(32)
250 SHOW_NEEDED(64)
251 }
252 if (!be_quiet && !found_needed)
253 printf(" - ");
254 else if (found_needed)
255 printf(" ");
256 }
257
258 /* search the symbol table for a specified symbol */
259 if (find_sym) {
260 void *symtab_void, *strtab_void;
261 char *versioned_symname;
262 size_t len;
263
264 len = strlen(find_sym) + 1;
265 versioned_symname = (char *)malloc(sizeof(char) * (len+1));
266 if (!versioned_symname) {
267 warnf("Could not malloc() mem for sym scan");
268 return;
269 }
270 sprintf(versioned_symname, "%s@", find_sym);
271
272 symtab_void = elf_findsecbyname(elf, ".symtab");
273 strtab_void = elf_findsecbyname(elf, ".strtab");
274
275 if (symtab_void && strtab_void) {
276#define FIND_SYM(B) \
277 if (elf->elf_class == ELFCLASS ## B) { \
278 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
279 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
280 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
281 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
282 char *symname; \
283 for (i = 0; i < cnt; ++i) { \
284 if (sym->st_name) { \
285 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
286 if (*find_sym == '*') { \
287 printf("%s(%s) %5lX %15s %s\n", \
288 ((found_sym == 0) ? "\n\t" : "\t"), \
289 (char *)basename(filename), \
290 (long)sym->st_size, \
291 (char *)get_elfstttype(sym->st_info), \
292 symname); \
293 found_sym = 1; \
294 } else if ((strcmp(find_sym, symname) == 0) || \
295 (strncmp(symname, versioned_symname, len) == 0)) \
296 found_sym++; \
297 } \
298 ++sym; \
299 } }
300 FIND_SYM(32)
301 FIND_SYM(64)
302 }
303 free(versioned_symname);
304 if (*find_sym != '*') {
305 if (found_sym)
306 printf(" %s ", find_sym);
307 else if (!be_quiet)
308 printf(" - ");
309 }
310 }
311
213 if (!be_quiet || found_pax || found_stack || found_textrel || found_rpath) 312 if (!be_quiet || found_pax || found_stack || found_textrel || \
214 puts(filename); 313 found_rpath || found_needed || found_sym)
314 printf("%s\n", filename);
215 315
216 unreadelf(elf); 316 unreadelf(elf);
217} 317}
218 318
219/* scan a directory for ET_EXEC files and print when we find one */ 319/* scan a directory for ET_EXEC files and print when we find one */
221{ 321{
222 register DIR *dir; 322 register DIR *dir;
223 register struct dirent *dentry; 323 register struct dirent *dentry;
224 struct stat st_top, st; 324 struct stat st_top, st;
225 char buf[_POSIX_PATH_MAX]; 325 char buf[_POSIX_PATH_MAX];
226 size_t len = 0; 326 size_t pathlen = 0, len = 0;
227 327
228 /* make sure path exists */ 328 /* make sure path exists */
229 if (lstat(path, &st_top) == -1) 329 if (lstat(path, &st_top) == -1)
230 return; 330 return;
231 331
240 warnf("could not opendir %s: %s", path, strerror(errno)); 340 warnf("could not opendir %s: %s", path, strerror(errno));
241 return; 341 return;
242 } 342 }
243 if (be_verbose) printf("%s: scanning dir\n", path); 343 if (be_verbose) printf("%s: scanning dir\n", path);
244 344
345 pathlen = strlen(path);
245 while ((dentry = readdir(dir))) { 346 while ((dentry = readdir(dir))) {
246 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 347 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
247 continue; 348 continue;
248 len = (strlen(path) + 2 + strlen(dentry->d_name)); 349 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
249 assert(len < sizeof(buf)); 350 if (len >= sizeof(buf)) {
250 strncpy(buf, path, len); 351 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
251 strncat(buf, "/", len); 352 continue;
252 strncat(buf, dentry->d_name, len); 353 }
253 buf[sizeof(buf)] = 0; 354 sprintf(buf, "%s/%s", path, dentry->d_name);
254 if (lstat(buf, &st) != -1) { 355 if (lstat(buf, &st) != -1) {
255 if (S_ISREG(st.st_mode)) 356 if (S_ISREG(st.st_mode))
256 scanelf_file(buf); 357 scanelf_file(buf);
257 else if (dir_recurse && S_ISDIR(st.st_mode)) { 358 else if (dir_recurse && S_ISDIR(st.st_mode)) {
258 if (dir_crossmount || (st_top.st_dev == st.st_dev)) 359 if (dir_crossmount || (st_top.st_dev == st.st_dev))
273 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 374 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
274 err("Unable to open ld.so.conf: %s", strerror(errno)); 375 err("Unable to open ld.so.conf: %s", strerror(errno));
275 376
276 scan_l = scan_ul = scan_ull = 0; 377 scan_l = scan_ul = scan_ull = 0;
277 378
278 path = malloc(_POSIX_PATH_MAX); 379 if ((path = malloc(_POSIX_PATH_MAX)) == NULL) {
380 warn("Can not malloc() memory for ldpath scanning");
381 return;
382 }
279 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 383 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
280 if (*path == '/') { 384 if (*path == '/') {
281 if ((p = strrchr(path, '\r')) != NULL) 385 if ((p = strrchr(path, '\r')) != NULL)
282 *p = 0; 386 *p = 0;
283 if ((p = strrchr(path, '\n')) != NULL) 387 if ((p = strrchr(path, '\n')) != NULL)
286 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 390 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1;
287 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 391 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1;
288 scanelf_dir(path); 392 scanelf_dir(path);
289 } 393 }
290 free(path); 394 free(path);
395 fclose(fp);
291 396
292 if (!scan_l) scanelf_dir("/lib"); 397 if (!scan_l) scanelf_dir("/lib");
293 if (!scan_ul) scanelf_dir("/usr/lib"); 398 if (!scan_ul) scanelf_dir("/usr/lib");
294 if (!scan_ull) scanelf_dir("/usr/local/lib"); 399 if (!scan_ull) scanelf_dir("/usr/local/lib");
295
296 fclose(fp);
297} 400}
298 401
299/* scan env PATH for paths */ 402/* scan env PATH for paths */
300static void scanelf_envpath() 403static void scanelf_envpath()
301{ 404{
304 path = getenv("PATH"); 407 path = getenv("PATH");
305 if (!path) 408 if (!path)
306 err("PATH is not set in your env !"); 409 err("PATH is not set in your env !");
307 410
308 if ((path = strdup(path)) == NULL) 411 if ((path = strdup(path)) == NULL)
309 err("stdup failed: %s", strerror(errno)); 412 err("strdup failed: %s", strerror(errno));
310 413
311 while ((p = strrchr(path, ':')) != NULL) { 414 while ((p = strrchr(path, ':')) != NULL) {
312 scanelf_dir(p + 1); 415 scanelf_dir(p + 1);
313 *p = 0; 416 *p = 0;
314 } 417 }
317} 420}
318 421
319 422
320 423
321/* usage / invocation handling functions */ 424/* usage / invocation handling functions */
322#define PARSE_FLAGS "plRmxetraqvo:BhV" 425#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
426#define a_argument required_argument
323static struct option const long_opts[] = { 427static struct option const long_opts[] = {
324 {"path", no_argument, NULL, 'p'}, 428 {"path", no_argument, NULL, 'p'},
325 {"ldpath", no_argument, NULL, 'l'}, 429 {"ldpath", no_argument, NULL, 'l'},
326 {"recursive", no_argument, NULL, 'R'}, 430 {"recursive", no_argument, NULL, 'R'},
327 {"mount", no_argument, NULL, 'm'}, 431 {"mount", no_argument, NULL, 'm'},
328 {"pax", no_argument, NULL, 'x'}, 432 {"pax", no_argument, NULL, 'x'},
329 {"header", no_argument, NULL, 'e'}, 433 {"header", no_argument, NULL, 'e'},
330 {"textrel", no_argument, NULL, 't'}, 434 {"textrel", no_argument, NULL, 't'},
331 {"rpath", no_argument, NULL, 'r'}, 435 {"rpath", no_argument, NULL, 'r'},
436 {"needed", no_argument, NULL, 'n'},
437 {"symbol", a_argument, NULL, 's'},
332 {"all", no_argument, NULL, 'a'}, 438 {"all", no_argument, NULL, 'a'},
333 {"quiet", no_argument, NULL, 'q'}, 439 {"quiet", no_argument, NULL, 'q'},
334 {"verbose", no_argument, NULL, 'v'}, 440 {"verbose", no_argument, NULL, 'v'},
335 {"file",required_argument, NULL, 'o'}, 441 {"file", a_argument, NULL, 'o'},
336 {"nobanner", no_argument, NULL, 'B'}, 442 {"nobanner", no_argument, NULL, 'B'},
337 {"help", no_argument, NULL, 'h'}, 443 {"help", no_argument, NULL, 'h'},
338 {"version", no_argument, NULL, 'V'}, 444 {"version", no_argument, NULL, 'V'},
339 {NULL, no_argument, NULL, 0x0} 445 {NULL, no_argument, NULL, 0x0}
340}; 446};
345 "Don't recursively cross mount points\n", 451 "Don't recursively cross mount points\n",
346 "Print PaX markings", 452 "Print PaX markings",
347 "Print GNU_STACK markings", 453 "Print GNU_STACK markings",
348 "Print TEXTREL information", 454 "Print TEXTREL information",
349 "Print RPATH information", 455 "Print RPATH information",
456 "Print NEEDED information",
457 "Find a specified symbol",
350 "Print all scanned info (-x -e -t -r)\n", 458 "Print all scanned info (-x -e -t -r)\n",
351 "Only output 'bad' things", 459 "Only output 'bad' things",
352 "Be verbose (can be specified more than once)", 460 "Be verbose (can be specified more than once)",
353 "Write output stream to a filename", 461 "Write output stream to a filename",
354 "Don't display the header", 462 "Don't display the header",
359 467
360/* display usage and exit */ 468/* display usage and exit */
361static void usage(int status) 469static void usage(int status)
362{ 470{
363 int i; 471 int i;
364 printf(" Scan ELF binaries for stuff\n\n" 472 printf(" Scan ELF binaries for stuff\n"
365 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 473 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
366 printf("Options:\n"); 474 printf("Options:\n");
367 for (i = 0; long_opts[i].name; ++i) 475 for (i = 0; long_opts[i].name; ++i)
476 if (long_opts[i].has_arg == no_argument)
368 printf(" -%c, --%-12s %s\n", long_opts[i].val, 477 printf(" -%c, --%-13s %s\n", long_opts[i].val,
369 long_opts[i].name, opts_help[i]); 478 long_opts[i].name, opts_help[i]);
370#ifdef MANLYPAGE 479 else
371 for (i = 0; long_opts[i].name; ++i) 480 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
372 printf(".TP\n\\fB\\-%c, \\-\\-%s\\fR\n%s\n", long_opts[i].val,
373 long_opts[i].name, opts_help[i]); 481 long_opts[i].name, opts_help[i]);
374#endif
375 exit(status); 482 exit(status);
376} 483}
377 484
378/* parse command line arguments and preform needed actions */ 485/* parse command line arguments and preform needed actions */
379static void parseargs(int argc, char *argv[]) 486static void parseargs(int argc, char *argv[])
388 printf("%s compiled %s\n%s\n" 495 printf("%s compiled %s\n%s\n"
389 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 496 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
390 __FILE__, __DATE__, rcsid, argv0); 497 __FILE__, __DATE__, rcsid, argv0);
391 exit(EXIT_SUCCESS); 498 exit(EXIT_SUCCESS);
392 break; 499 break;
393 case 's': /* reserved for -s, --symbol= */
394 case 'h': usage(EXIT_SUCCESS); break; 500 case 'h': usage(EXIT_SUCCESS); break;
395 501
396 case 'o': { 502 case 'o': {
397 FILE *fp = NULL; 503 FILE *fp = NULL;
398 fp = freopen(optarg, "w", stdout); 504 fp = freopen(optarg, "w", stdout);
399 if (fp == NULL) 505 if (fp == NULL)
400 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 506 err("Could not open output stream '%s': %s", optarg, strerror(errno));
401 stdout = fp; 507 stdout = fp;
402 break; 508 break;
403 } 509 }
510
511 case 's': find_sym = strdup(optarg); break;
404 512
405 case 'B': show_banner = 0; break; 513 case 'B': show_banner = 0; break;
406 case 'l': scan_ldpath = 1; break; 514 case 'l': scan_ldpath = 1; break;
407 case 'p': scan_envpath = 1; break; 515 case 'p': scan_envpath = 1; break;
408 case 'R': dir_recurse = 1; break; 516 case 'R': dir_recurse = 1; break;
409 case 'm': dir_crossmount = 0; break; 517 case 'm': dir_crossmount = 0; break;
410 case 'x': show_pax = 1; break; 518 case 'x': show_pax = 1; break;
411 case 'e': show_stack = 1; break; 519 case 'e': show_stack = 1; break;
412 case 't': show_textrel = 1; break; 520 case 't': show_textrel = 1; break;
413 case 'r': show_rpath = 1; break; 521 case 'r': show_rpath = 1; break;
522 case 'n': show_needed = 1; break;
414 case 'q': be_quiet = 1; break; 523 case 'q': be_quiet = 1; break;
415 case 'v': be_verbose = (be_verbose % 20) + 1; break; 524 case 'v': be_verbose = (be_verbose % 20) + 1; break;
416 case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break; 525 case 'a': show_pax = show_stack = show_textrel = show_needed = show_rpath = 1; break;
417 526
418 case ':': 527 case ':':
419 warn("Option missing parameter"); 528 warn("Option missing parameter");
420 usage(EXIT_FAILURE); 529 usage(EXIT_FAILURE);
421 break; 530 break;
436 if (scan_envpath) scanelf_envpath(); 545 if (scan_envpath) scanelf_envpath();
437 if (optind == argc && !scan_ldpath && !scan_envpath) 546 if (optind == argc && !scan_ldpath && !scan_envpath)
438 err("Nothing to scan !?"); 547 err("Nothing to scan !?");
439 while (optind < argc) 548 while (optind < argc)
440 scanelf_dir(argv[optind++]); 549 scanelf_dir(argv[optind++]);
550
551 if (find_sym) free(find_sym);
441} 552}
442 553
443 554
444 555
445int main(int argc, char *argv[]) 556int main(int argc, char *argv[])

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.32

  ViewVC Help
Powered by ViewVC 1.1.20