/[gentoo-projects]/pax-utils/scanelf.c
Gentoo

Contents of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide annotations) (download) (as text)
Thu Mar 31 00:50:56 2005 UTC (9 years, 4 months ago) by solar
Branch: MAIN
Changes since 1.11: +22 -15 lines
File MIME type: text/x-csrc
- update formatting to not be so ulgy

1 solar 1.1 /*
2     * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 vapier 1.8 * Copyright 1999-2005 Gentoo Foundation
4 solar 1.1 * Distributed under the terms of the GNU General Public License v2
5 solar 1.12 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.11 2005/03/31 00:03:25 solar Exp $
6 solar 1.1 *
7     ********************************************************************
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
10     * published by the Free Software Foundation; either version 2 of the
11     * License, or (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful, but
14     * WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16     * General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21     * MA 02111-1307, USA.
22     */
23    
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <sys/types.h>
27     #include <string.h>
28 vapier 1.10 #include <errno.h>
29 solar 1.1 #include <unistd.h>
30     #include <sys/stat.h>
31     #include <dirent.h>
32     #include <getopt.h>
33    
34     #include "paxelf.h"
35    
36 solar 1.12 static const char *rcsid = "$Id: scanelf.c,v 1.11 2005/03/31 00:03:25 solar Exp $";
37 vapier 1.10
38    
39     /* helper functions for showing errors */
40     #define argv0 "scanelf\0" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
41     #define warn(fmt, args...) \
42     fprintf(stderr, "%s: " fmt "\n", argv0, ## args)
43     #define warnf(fmt, args...) warn("%s(): " fmt, __FUNCTION__, ## args)
44     #define err(fmt, args...) \
45     do { \
46     warn(fmt, ## args); \
47     exit(EXIT_FAILURE); \
48     } while (0)
49    
50    
51    
52     /* prototypes */
53     static void scanelf_file(const char *filename);
54     static void scanelf_dir(const char *path);
55     static void scanelf_ldpath();
56     static void scanelf_envpath();
57     static void usage(int status);
58     static void parseargs(int argc, char *argv[]);
59    
60     /* variables to control behavior */
61     static char scan_ldpath = 0;
62     static char scan_envpath = 0;
63     static char dir_recurse = 0;
64     static char show_pax = 0;
65     static char show_stack = 0;
66     static char show_textrel = 0;
67     static char show_rpath = 0;
68     static char show_header = 1;
69     static char be_quiet = 0;
70    
71 solar 1.1
72    
73 vapier 1.10 /* scan an elf file and show all the fun stuff */
74     static void scanelf_file(const char *filename)
75 solar 1.6 {
76 vapier 1.10 int i;
77 solar 1.12 char found_stack, found_relro, found_textrel, found_rpath;
78 vapier 1.10 Elf_Dyn *dyn;
79     elfobj *elf = NULL;
80    
81 solar 1.12 found_stack = found_relro = found_textrel = found_rpath = 0;
82    
83 vapier 1.10 /* verify this is real ELF */
84     if ((elf = readelf(filename)) == NULL)
85     return;
86     if (check_elf_header(elf->ehdr) || !IS_ELF(elf))
87     goto bail;
88    
89     /* show the header */
90     if (!be_quiet && show_header) {
91 solar 1.12 fputs(" TYPE ", stderr);
92     if (show_pax) fputs(" PAX ", stderr);
93     if (show_stack) fputs(" STACK ", stderr);
94     if (show_textrel) fputs(" TEXTREL ", stderr);
95     if (show_rpath) fputs(" RPATH ", stderr);
96     fputs(" FILE\n", stderr);
97 vapier 1.10 show_header = 0;
98     }
99    
100     /* dump all the good stuff */
101     if (!be_quiet)
102     printf("%-7s ", get_elfetype(elf->ehdr->e_type));
103    
104     if (show_pax)
105     printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
106    
107     /* stack fun */
108     if (show_stack) {
109     for (i = 0; i < elf->ehdr->e_phnum; i++) {
110     if (elf->phdr[i].p_type != PT_GNU_STACK && \
111     elf->phdr[i].p_type != PT_GNU_RELRO) continue;
112    
113     if (be_quiet && !(elf->phdr[i].p_flags & PF_X))
114     continue;
115    
116 solar 1.12 if (elf->phdr[i].p_type == PT_GNU_STACK)
117     found_stack = 1;
118     if (elf->phdr[i].p_type == PT_GNU_RELRO)
119     found_relro = 1;
120    
121 vapier 1.10 printf("%s ", gnu_short_stack_flags(elf->phdr[i].p_flags));
122     }
123 solar 1.12 if (!be_quiet && !found_stack) fputs("--- ", stdout);
124     if (!be_quiet && !found_relro) fputs("--- ", stdout);
125 vapier 1.10 }
126    
127     /* textrel fun */
128     if (show_textrel) {
129     for (i = 0; i < elf->ehdr->e_phnum; i++) {
130     if (elf->phdr[i].p_type != PT_DYNAMIC) continue;
131    
132     dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
133     while (dyn->d_tag != DT_NULL) {
134     if (dyn->d_tag == DT_TEXTREL) { //dyn->d_tag != DT_FLAGS)
135     found_textrel = 1;
136     // if (dyn->d_un.d_val & DF_TEXTREL)
137 solar 1.12 fputs("TEXTREL ", stdout);
138 vapier 1.10 }
139     ++dyn;
140     }
141     }
142 solar 1.12 if (!be_quiet && !found_textrel) fputs("------- ", stdout);
143 vapier 1.10 }
144    
145     /* rpath fun */
146     /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
147     if (show_rpath) {
148     Elf_Shdr *strtbl = elf_findsecbyname(elf, ".dynstr");
149    
150     if (strtbl)
151     for (i = 0; i < elf->ehdr->e_phnum; i++) {
152     if (elf->phdr[i].p_type != PT_DYNAMIC) continue;
153    
154     dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
155     while (dyn->d_tag != DT_NULL) {
156     if (dyn->d_tag == DT_RPATH) { //|| dyn->d_tag != DT_RUNPATH)
157     char *rpath = elf->data + strtbl->sh_offset + dyn->d_un.d_ptr;
158     found_rpath = 1;
159     printf("%s ", rpath);
160     }
161     ++dyn;
162     }
163     }
164 solar 1.12 if (!be_quiet && !found_rpath) fputs("- ", stdout);
165 vapier 1.10 }
166    
167     if (!be_quiet || show_pax || found_stack || found_textrel || found_rpath)
168     printf("%s\n", filename);
169    
170     bail:
171     unreadelf(elf);
172 solar 1.6 }
173    
174 solar 1.1 /* scan a directory for ET_EXEC files and print when we find one */
175 vapier 1.10 static void scanelf_dir(const char *path)
176 solar 1.1 {
177 vapier 1.10 register DIR *dir;
178     register struct dirent *dentry;
179     struct stat st;
180     char *p;
181     int len = 0;
182    
183     /* make sure path exists */
184     if (lstat(path, &st) == -1)
185     return;
186 solar 1.11
187 vapier 1.10 /* ok, if it isn't a directory, assume we can open it */
188     if (!S_ISDIR(st.st_mode)) {
189     scanelf_file(path);
190     return;
191     }
192    
193     /* now scan the dir looking for fun stuff */
194     if ((dir = opendir(path)) == NULL) {
195     warnf("could not opendir %s: %s", path, strerror(errno));
196     return;
197     }
198 solar 1.11
199 vapier 1.10 while ((dentry = readdir(dir))) {
200     if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
201     continue;
202     len = (strlen(path) + 2 + strlen(dentry->d_name));
203     p = malloc(len);
204     if (!p)
205     err("scanelf_dir(): Could not malloc: %s", strerror(errno));
206     strncpy(p, path, len);
207     strncat(p, "/", len);
208     strncat(p, dentry->d_name, len);
209     if (lstat(p, &st) != -1) {
210     if (S_ISREG(st.st_mode))
211     scanelf_file(p);
212     else if (dir_recurse && S_ISDIR(st.st_mode)) {
213     scanelf_dir(p);
214     }
215     }
216     free(p);
217     }
218     closedir(dir);
219 solar 1.1 }
220    
221 vapier 1.10 /* scan /etc/ld.so.conf for paths */
222     static void scanelf_ldpath()
223     {
224     char *path, *p;
225     FILE *fp;
226    
227     if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
228     err("Unable to open ld.so.conf: %s", strerror(errno));
229    
230     path = malloc(_POSIX_PATH_MAX);
231     while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
232     if (*path == '/') {
233     if ((p = strrchr(path, '\r')) != NULL)
234     *p = 0;
235     if ((p = strrchr(path, '\n')) != NULL)
236     *p = 0;
237     scanelf_dir(path);
238     }
239     free(path);
240    
241     fclose(fp);
242     }
243 solar 1.1
244 vapier 1.10 /* scan env PATH for paths */
245     static void scanelf_envpath()
246 solar 1.1 {
247 vapier 1.10 char *path, *p;
248    
249     path = getenv("PATH");
250     if (!path)
251     err("PATH is not set in your env !");
252    
253     if ((path = strdup(path)) == NULL)
254     err("stdup failed: %s", strerror(errno));
255    
256     while ((p = strrchr(path, ':')) != NULL) {
257     scanelf_dir(p + 1);
258     *p = 0;
259     }
260     free(path);
261 solar 1.1 }
262    
263    
264 vapier 1.10
265     /* usage / invocation handling functions */
266     #define PARSE_FLAGS "plRxstraqhV"
267     static struct option const long_opts[] = {
268     {"path", no_argument, NULL, 'p'},
269     {"ldpath", no_argument, NULL, 'l'},
270     {"recursive", no_argument, NULL, 'R'},
271     {"pax", no_argument, NULL, 'x'},
272     {"stack", no_argument, NULL, 's'},
273     {"textrel", no_argument, NULL, 't'},
274     {"rpath", no_argument, NULL, 'r'},
275     {"all", no_argument, NULL, 'a'},
276     {"quiet", no_argument, NULL, 'q'},
277     /* {"vebose", no_argument, NULL, 'v'},*/
278     {"help", no_argument, NULL, 'h'},
279     {"version", no_argument, NULL, 'V'},
280     {NULL, no_argument, NULL, 0x0}
281     };
282     static char *opts_help[] = {
283     "Scan all directories in PATH environment",
284     "Scan all directories in /etc/ld.so.conf",
285     "Scan directories recursively\n",
286     "Print PaX markings",
287     "Print GNU_STACK markings",
288     "Print TEXTREL information",
289     "Print RPATH information",
290     "Print all scanned info",
291     "Only output 'bad' things\n",
292     /* "Be verbose !",*/
293     "Print this help and exit",
294     "Print version and exit",
295     NULL
296     };
297    
298     /* display usage and exit */
299     static void usage(int status)
300 solar 1.1 {
301 vapier 1.10 int i;
302     printf(" Scan ELF binaries for stuff\n\n"
303     "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
304 solar 1.12 fputs("Options:\n", stdout);
305 vapier 1.10 for (i = 0; long_opts[i].name; ++i)
306     printf(" -%c, --%-12s %s\n", long_opts[i].val,
307     long_opts[i].name, opts_help[i]);
308     exit(status);
309 solar 1.1 }
310    
311     /* parse command line arguments and preform needed actions */
312 vapier 1.10 static void parseargs(int argc, char *argv[])
313     {
314     int flag;
315    
316     opterr = 0;
317     while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
318     switch (flag) {
319    
320     case 'V': /* version info */
321     printf("%s compiled %s\n"
322 solar 1.11 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n"
323 vapier 1.10 "%s\n",
324     __FILE__, __DATE__, argv0, rcsid);
325     exit(EXIT_SUCCESS);
326     break;
327     case 'h': usage(EXIT_SUCCESS); break;
328    
329     case 'l': scan_ldpath = 1; break;
330     case 'p': scan_envpath = 1; break;
331     case 'R': dir_recurse = 1; break;
332     case 'x': show_pax = 1; break;
333     case 's': show_stack = 1; break;
334     case 't': show_textrel = 1; break;
335     case 'r': show_rpath = 1; break;
336     case 'q': be_quiet = 1; break;
337     case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break;
338    
339     case ':':
340     warn("Option missing parameter");
341     usage(EXIT_FAILURE);
342     break;
343     case '?':
344     warn("Unknown option");
345     usage(EXIT_FAILURE);
346     break;
347     default:
348     err("Unhandled option '%c'", flag);
349     break;
350     }
351     }
352    
353     if (scan_ldpath) scanelf_ldpath();
354     if (scan_envpath) scanelf_envpath();
355     while (optind < argc)
356     scanelf_dir(argv[optind++]);
357     }
358    
359    
360    
361     int main(int argc, char *argv[])
362 solar 1.1 {
363 vapier 1.10 if (argc < 2)
364     usage(EXIT_FAILURE);
365     parseargs(argc, argv);
366     return EXIT_SUCCESS;
367 solar 1.1 }

  ViewVC Help
Powered by ViewVC 1.1.20