/[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.28 Revision 1.35
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.28 2005/04/05 03:41:27 solar Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.35 2005/04/14 00:17:30 solar 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.28 2005/04/05 03:41:27 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.35 2005/04/14 00:17:30 solar Exp $";
39 39
40 40
41/* helper functions for showing errors */ 41/* helper functions for showing errors */
42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/ 42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
43#define warn(fmt, args...) \ 43#define warn(fmt, args...) \
66static char dir_crossmount = 1; 66static char dir_crossmount = 1;
67static char show_pax = 0; 67static char show_pax = 0;
68static char show_stack = 0; 68static char show_stack = 0;
69static char show_textrel = 0; 69static char show_textrel = 0;
70static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
71static char show_banner = 1; 72static char show_banner = 1;
72static char be_quiet = 0; 73static char be_quiet = 0;
73static char be_verbose = 0; 74static char be_verbose = 0;
74static char *find_sym = NULL; 75static char *find_sym = NULL;
75 76
77 78
78/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
79static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
80{ 81{
81 int i; 82 int i;
82 char found_pax, found_stack, found_relro, found_textrel, found_rpath, found_sym; 83 char found_pax, found_stack, found_relro, found_textrel,
84 found_rpath, found_needed, found_sym;
83 elfobj *elf; 85 elfobj *elf;
86 struct stat st;
84 87
88 /* make sure path exists */
89 if (lstat(filename, &st) == -1)
90 return;
91 if (!S_ISREG(st.st_mode))
92 return;
85 found_pax = found_stack = found_relro = found_textrel = found_rpath = found_sym = 0; 93 found_pax = found_stack = found_relro = found_textrel = \
94 found_rpath = found_needed = found_sym = 0;
86 95
87 /* verify this is real ELF */ 96 /* verify this is real ELF */
88 if ((elf = readelf(filename)) == NULL) { 97 if ((elf = readelf(filename)) == NULL) {
89 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 98 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
90 return; 99 return;
97 else if (be_verbose) 106 else if (be_verbose)
98 printf("%s: scanning file\n", filename); 107 printf("%s: scanning file\n", filename);
99 108
100 /* show the header */ 109 /* show the header */
101 if (!be_quiet && show_banner) { 110 if (!be_quiet && show_banner) {
102 printf(" TYPE "); 111 printf(" TYPE ");
103 if (show_pax) printf(" PAX "); 112 if (show_pax) printf(" PAX ");
104 if (show_stack) printf(" STK/REL "); 113 if (show_stack) printf("STK/REL ");
105 if (show_textrel) printf("TEXTREL "); 114 if (show_textrel) printf("TEXTREL ");
106 if (show_rpath) printf("RPATH "); 115 if (show_rpath) printf("RPATH ");
116 if (show_needed) printf("NEEDED ");
107 printf(" FILE\n"); 117 printf(" FILE\n");
108 show_banner = 0; 118 show_banner = 0;
109 } 119 }
110 120
111 /* dump all the good stuff */ 121 /* dump all the good stuff */
156 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 166 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
157 while (EGET(dyn->d_tag) != DT_NULL) { \ 167 while (EGET(dyn->d_tag) != DT_NULL) { \
158 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 168 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
159 found_textrel = 1; \ 169 found_textrel = 1; \
160 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 170 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
161 printf("TEXTREL "); \ 171 fputs("TEXTREL ", stdout); \
162 } \ 172 } \
163 ++dyn; \ 173 ++dyn; \
164 } \ 174 } \
165 } } 175 } }
166 SHOW_TEXTREL(32) 176 SHOW_TEXTREL(32)
167 SHOW_TEXTREL(64) 177 SHOW_TEXTREL(64)
168 if (!be_quiet && !found_textrel) printf("------- "); 178 if (!be_quiet && !found_textrel) fputs("------- ", stdout);
169 } 179 }
170 180
171 /* rpath fun */ 181 /* rpath fun */
172 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 182 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
173 if (show_rpath) { 183 if (show_rpath) {
210 printf("%-5s ", (runpath ? runpath : rpath)); 220 printf("%-5s ", (runpath ? runpath : rpath));
211 else if (!be_quiet && !found_rpath) 221 else if (!be_quiet && !found_rpath)
212 printf(" - "); 222 printf(" - ");
213 } 223 }
214 224
225 /* print out all the NEEDED entries */
226 if (show_needed) {
227 char *needed;
228 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
229
230 if (strtbl_void) {
231#define SHOW_NEEDED(B) \
232 if (elf->elf_class == ELFCLASS ## B) { \
233 Elf ## B ## _Dyn *dyn; \
234 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
235 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
236 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
237 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
238 if (be_verbose && EGET(phdr[i].p_type) == PT_INTERP) { \
239 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
240 printf("%s\n", elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr)); \
241 exit(0); \
242 } \
243 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
244 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
245 while (EGET(dyn->d_tag) != DT_NULL) { \
246 if (EGET(dyn->d_tag) == DT_NEEDED) { \
247 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
248 if (found_needed) printf(","); \
249 printf("%s", needed); \
250 found_needed = 1; \
251 } \
252 ++dyn; \
253 } \
254 } }
255 SHOW_NEEDED(32)
256 SHOW_NEEDED(64)
257 }
258 if (!be_quiet && !found_needed)
259 printf(" - ");
260 else if (found_needed)
261 printf(" ");
262 }
263
264 /* search the symbol table for a specified symbol */
215 if (find_sym) { 265 if (find_sym) {
216 void *symtab_void, *strtab_void; 266 void *symtab_void, *strtab_void;
217 char found_sym = 0; 267 char *versioned_symname;
218 char *versioned_symname = malloc(strlen(find_sym)+1); 268 size_t len;
219 269
270 len = strlen(find_sym) + 1;
271 versioned_symname = (char *)malloc(sizeof(char) * (len+1));
272 if (!versioned_symname) {
273 warnf("Could not malloc() mem for sym scan");
274 return;
275 }
220 sprintf(versioned_symname, "%s@", find_sym); 276 sprintf(versioned_symname, "%s@", find_sym);
277
221 symtab_void = elf_findsecbyname(elf, ".symtab"); 278 symtab_void = elf_findsecbyname(elf, ".symtab");
222 strtab_void = elf_findsecbyname(elf, ".strtab"); 279 strtab_void = elf_findsecbyname(elf, ".strtab");
223 280
224 if (symtab_void && strtab_void) { 281 if (symtab_void && strtab_void) {
225#define FIND_SYM(B) \ 282#define FIND_SYM(B) \
231 char *symname; \ 288 char *symname; \
232 for (i = 0; i < cnt; ++i) { \ 289 for (i = 0; i < cnt; ++i) { \
233 if (sym->st_name) { \ 290 if (sym->st_name) { \
234 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 291 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
235 if (*find_sym == '*') { \ 292 if (*find_sym == '*') { \
236 printf("%s(%s) %5lX %15s %s\n", ((found_sym == 0) ? "\n\t" : "\t"), \ 293 printf("%s(%s) %5lX %15s %s\n", \
294 ((found_sym == 0) ? "\n\t" : "\t"), \
237 (char *) basename(filename), \ 295 (char *)basename(filename), \
238 (long)sym->st_size, (char *) get_elfstttype(sym->st_info & 0xF), \ 296 (long)sym->st_size, \
239 symname); \ 297 (char *)get_elfstttype(sym->st_info), \
298 symname); \
240 found_sym = 1; \ 299 found_sym = 1; \
241 } \
242 if ((strcmp(find_sym, symname) == 0) || \ 300 } else if ((strcmp(find_sym, symname) == 0) || \
243 (strncmp(symname, versioned_symname, strlen(versioned_symname)) == 0)) \ 301 (strncmp(symname, versioned_symname, len) == 0)) \
244 found_sym++; \ 302 found_sym++; \
245 } \ 303 } \
246 ++sym; \ 304 ++sym; \
247 } } 305 } }
248 FIND_SYM(32) 306 FIND_SYM(32)
249 FIND_SYM(64) 307 FIND_SYM(64)
250 } 308 }
251 free(versioned_symname); 309 free(versioned_symname);
252 if (*find_sym != '*') 310 if (*find_sym != '*') {
253 printf(" %s ", (found_sym == 0) ? "-" : find_sym); 311 if (found_sym)
312 printf(" %s ", find_sym);
313 else if (!be_quiet)
314 fputs(" - ", stdout);
254 } 315 }
316 }
255 317
256 if (!be_quiet || found_pax || found_stack || found_textrel || found_rpath) 318 if (!be_quiet || found_pax || found_stack || found_textrel || \
257 printf("%s\n", filename); 319 found_rpath || found_needed || found_sym)
320 puts(filename);
258 321
259 unreadelf(elf); 322 unreadelf(elf);
260} 323}
261 324
262/* scan a directory for ET_EXEC files and print when we find one */ 325/* scan a directory for ET_EXEC files and print when we find one */
264{ 327{
265 register DIR *dir; 328 register DIR *dir;
266 register struct dirent *dentry; 329 register struct dirent *dentry;
267 struct stat st_top, st; 330 struct stat st_top, st;
268 char buf[_POSIX_PATH_MAX]; 331 char buf[_POSIX_PATH_MAX];
269 size_t len = 0; 332 size_t pathlen = 0, len = 0;
270 333
271 /* make sure path exists */ 334 /* make sure path exists */
272 if (lstat(path, &st_top) == -1) 335 if (lstat(path, &st_top) == -1)
273 return; 336 return;
274 337
283 warnf("could not opendir %s: %s", path, strerror(errno)); 346 warnf("could not opendir %s: %s", path, strerror(errno));
284 return; 347 return;
285 } 348 }
286 if (be_verbose) printf("%s: scanning dir\n", path); 349 if (be_verbose) printf("%s: scanning dir\n", path);
287 350
351 pathlen = strlen(path);
288 while ((dentry = readdir(dir))) { 352 while ((dentry = readdir(dir))) {
289 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 353 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
290 continue; 354 continue;
291 len = (strlen(path) + 2 + strlen(dentry->d_name)); 355 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
292 assert(len < sizeof(buf)); 356 if (len >= sizeof(buf)) {
293 strncpy(buf, path, len); 357 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
294 strncat(buf, "/", len); 358 continue;
295 strncat(buf, dentry->d_name, len); 359 }
296 buf[sizeof(buf)] = 0; 360 sprintf(buf, "%s/%s", path, dentry->d_name);
297 if (lstat(buf, &st) != -1) { 361 if (lstat(buf, &st) != -1) {
298 if (S_ISREG(st.st_mode)) 362 if (S_ISREG(st.st_mode))
299 scanelf_file(buf); 363 scanelf_file(buf);
300 else if (dir_recurse && S_ISDIR(st.st_mode)) { 364 else if (dir_recurse && S_ISDIR(st.st_mode)) {
301 if (dir_crossmount || (st_top.st_dev == st.st_dev)) 365 if (dir_crossmount || (st_top.st_dev == st.st_dev))
316 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 380 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
317 err("Unable to open ld.so.conf: %s", strerror(errno)); 381 err("Unable to open ld.so.conf: %s", strerror(errno));
318 382
319 scan_l = scan_ul = scan_ull = 0; 383 scan_l = scan_ul = scan_ull = 0;
320 384
321 path = malloc(_POSIX_PATH_MAX); 385 if ((path = malloc(_POSIX_PATH_MAX)) == NULL) {
386 warn("Can not malloc() memory for ldpath scanning");
387 return;
388 }
322 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 389 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
323 if (*path == '/') { 390 if (*path == '/') {
324 if ((p = strrchr(path, '\r')) != NULL) 391 if ((p = strrchr(path, '\r')) != NULL)
325 *p = 0; 392 *p = 0;
326 if ((p = strrchr(path, '\n')) != NULL) 393 if ((p = strrchr(path, '\n')) != NULL)
329 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 396 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1;
330 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 397 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1;
331 scanelf_dir(path); 398 scanelf_dir(path);
332 } 399 }
333 free(path); 400 free(path);
401 fclose(fp);
334 402
335 if (!scan_l) scanelf_dir("/lib"); 403 if (!scan_l) scanelf_dir("/lib");
336 if (!scan_ul) scanelf_dir("/usr/lib"); 404 if (!scan_ul) scanelf_dir("/usr/lib");
337 if (!scan_ull) scanelf_dir("/usr/local/lib"); 405 if (!scan_ull) scanelf_dir("/usr/local/lib");
338
339 fclose(fp);
340} 406}
341 407
342/* scan env PATH for paths */ 408/* scan env PATH for paths */
343static void scanelf_envpath() 409static void scanelf_envpath()
344{ 410{
347 path = getenv("PATH"); 413 path = getenv("PATH");
348 if (!path) 414 if (!path)
349 err("PATH is not set in your env !"); 415 err("PATH is not set in your env !");
350 416
351 if ((path = strdup(path)) == NULL) 417 if ((path = strdup(path)) == NULL)
352 err("stdup failed: %s", strerror(errno)); 418 err("strdup failed: %s", strerror(errno));
353 419
354 while ((p = strrchr(path, ':')) != NULL) { 420 while ((p = strrchr(path, ':')) != NULL) {
355 scanelf_dir(p + 1); 421 scanelf_dir(p + 1);
356 *p = 0; 422 *p = 0;
357 } 423 }
360} 426}
361 427
362 428
363 429
364/* usage / invocation handling functions */ 430/* usage / invocation handling functions */
365#define PARSE_FLAGS "plRmxetrs:aqvo:BhV" 431#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
366#define a_argument required_argument 432#define a_argument required_argument
367static struct option const long_opts[] = { 433static struct option const long_opts[] = {
368 {"path", no_argument, NULL, 'p'}, 434 {"path", no_argument, NULL, 'p'},
369 {"ldpath", no_argument, NULL, 'l'}, 435 {"ldpath", no_argument, NULL, 'l'},
370 {"recursive", no_argument, NULL, 'R'}, 436 {"recursive", no_argument, NULL, 'R'},
371 {"mount", no_argument, NULL, 'm'}, 437 {"mount", no_argument, NULL, 'm'},
372 {"pax", no_argument, NULL, 'x'}, 438 {"pax", no_argument, NULL, 'x'},
373 {"header", no_argument, NULL, 'e'}, 439 {"header", no_argument, NULL, 'e'},
374 {"textrel", no_argument, NULL, 't'}, 440 {"textrel", no_argument, NULL, 't'},
375 {"rpath", no_argument, NULL, 'r'}, 441 {"rpath", no_argument, NULL, 'r'},
442 {"needed", no_argument, NULL, 'n'},
376 {"symbol", a_argument, NULL, 's'}, 443 {"symbol", a_argument, NULL, 's'},
377 {"all", no_argument, NULL, 'a'}, 444 {"all", no_argument, NULL, 'a'},
378 {"quiet", no_argument, NULL, 'q'}, 445 {"quiet", no_argument, NULL, 'q'},
379 {"verbose", no_argument, NULL, 'v'}, 446 {"verbose", no_argument, NULL, 'v'},
380 {"file", a_argument, NULL, 'o'}, 447 {"file", a_argument, NULL, 'o'},
390 "Don't recursively cross mount points\n", 457 "Don't recursively cross mount points\n",
391 "Print PaX markings", 458 "Print PaX markings",
392 "Print GNU_STACK markings", 459 "Print GNU_STACK markings",
393 "Print TEXTREL information", 460 "Print TEXTREL information",
394 "Print RPATH information", 461 "Print RPATH information",
462 "Print NEEDED information",
395 "Find a specified symbol", 463 "Find a specified symbol",
396 "Print all scanned info (-x -e -t -r)\n", 464 "Print all scanned info (-x -e -t -r)\n",
397 "Only output 'bad' things", 465 "Only output 'bad' things",
398 "Be verbose (can be specified more than once)", 466 "Be verbose (can be specified more than once)",
399 "Write output stream to a filename", 467 "Write output stream to a filename",
406/* display usage and exit */ 474/* display usage and exit */
407static void usage(int status) 475static void usage(int status)
408{ 476{
409 int i; 477 int i;
410 printf(" Scan ELF binaries for stuff\n" 478 printf(" Scan ELF binaries for stuff\n"
411 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 479 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
412 printf("Options:\n"); 480 printf("Options: -[%s]\n", PARSE_FLAGS);
413 for (i = 0; long_opts[i].name; ++i) 481 for (i = 0; long_opts[i].name; ++i)
414 if (long_opts[i].has_arg == no_argument) 482 if (long_opts[i].has_arg == no_argument)
415 printf(" -%c, --%-13s %s\n", long_opts[i].val, 483 printf(" -%c, --%-13s %s\n", long_opts[i].val,
416 long_opts[i].name, opts_help[i]); 484 long_opts[i].name, opts_help[i]);
417 else 485 else
455 case 'm': dir_crossmount = 0; break; 523 case 'm': dir_crossmount = 0; break;
456 case 'x': show_pax = 1; break; 524 case 'x': show_pax = 1; break;
457 case 'e': show_stack = 1; break; 525 case 'e': show_stack = 1; break;
458 case 't': show_textrel = 1; break; 526 case 't': show_textrel = 1; break;
459 case 'r': show_rpath = 1; break; 527 case 'r': show_rpath = 1; break;
528 case 'n': show_needed = 1; break;
460 case 'q': be_quiet = 1; break; 529 case 'q': be_quiet = 1; break;
461 case 'v': be_verbose = (be_verbose % 20) + 1; break; 530 case 'v': be_verbose = (be_verbose % 20) + 1; break;
462 case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break; 531 case 'a': show_pax = show_stack = show_textrel = show_needed = show_rpath = 1; break;
463 532
464 case ':': 533 case ':':
465 warn("Option missing parameter"); 534 warn("Option missing parameter");
466 usage(EXIT_FAILURE); 535 usage(EXIT_FAILURE);
467 break; 536 break;

Legend:
Removed from v.1.28  
changed lines
  Added in v.1.35

  ViewVC Help
Powered by ViewVC 1.1.20