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

Contents of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (hide annotations) (download) (as text)
Thu Mar 31 00:03:25 2005 UTC (9 years, 5 months ago) by solar
Branch: MAIN
Changes since 1.10: +5 -3 lines
File MIME type: text/x-csrc
- update authors

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.11 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.10 2005/03/30 23:43:30 vapier 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.11 static const char *rcsid = "$Id: scanelf.c,v 1.10 2005/03/30 23:43:30 vapier 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     char found_stack = 0, found_textrel = 0, found_rpath = 0;
78     Elf_Dyn *dyn;
79     elfobj *elf = NULL;
80    
81     /* verify this is real ELF */
82     if ((elf = readelf(filename)) == NULL)
83     return;
84     if (check_elf_header(elf->ehdr) || !IS_ELF(elf))
85     goto bail;
86    
87     /* show the header */
88     if (!be_quiet && show_header) {
89     printf("TYPE ");
90     if (show_pax) printf("PAX ");
91     if (show_stack) printf("STACK ");
92     if (show_textrel) printf("TEXTREL ");
93     if (show_rpath) printf("RPATH ");
94     printf("FILE\n");
95     show_header = 0;
96     }
97    
98     /* dump all the good stuff */
99     if (!be_quiet)
100     printf("%-7s ", get_elfetype(elf->ehdr->e_type));
101    
102     if (show_pax)
103     printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
104    
105     /* stack fun */
106     if (show_stack) {
107     for (i = 0; i < elf->ehdr->e_phnum; i++) {
108     if (elf->phdr[i].p_type != PT_GNU_STACK && \
109     elf->phdr[i].p_type != PT_GNU_RELRO) continue;
110    
111     if (be_quiet && !(elf->phdr[i].p_flags & PF_X))
112     continue;
113    
114     found_stack = 1;
115     printf("%s ", gnu_short_stack_flags(elf->phdr[i].p_flags));
116     }
117     if (!be_quiet && !found_stack) printf("- ");
118     }
119    
120     /* textrel fun */
121     if (show_textrel) {
122     for (i = 0; i < elf->ehdr->e_phnum; i++) {
123     if (elf->phdr[i].p_type != PT_DYNAMIC) continue;
124    
125     dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
126     while (dyn->d_tag != DT_NULL) {
127     if (dyn->d_tag == DT_TEXTREL) { //dyn->d_tag != DT_FLAGS)
128     found_textrel = 1;
129     // if (dyn->d_un.d_val & DF_TEXTREL)
130     printf("TEXTREL ");
131     }
132     ++dyn;
133     }
134     }
135     if (!be_quiet && !found_textrel) printf("- ");
136     }
137    
138     /* rpath fun */
139     /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
140     if (show_rpath) {
141     Elf_Shdr *strtbl = elf_findsecbyname(elf, ".dynstr");
142    
143     if (strtbl)
144     for (i = 0; i < elf->ehdr->e_phnum; i++) {
145     if (elf->phdr[i].p_type != PT_DYNAMIC) continue;
146    
147     dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
148     while (dyn->d_tag != DT_NULL) {
149     if (dyn->d_tag == DT_RPATH) { //|| dyn->d_tag != DT_RUNPATH)
150     char *rpath = elf->data + strtbl->sh_offset + dyn->d_un.d_ptr;
151     found_rpath = 1;
152     printf("%s ", rpath);
153     }
154     ++dyn;
155     }
156     }
157     if (!be_quiet && !found_rpath) printf("- ");
158     }
159    
160     if (!be_quiet || show_pax || found_stack || found_textrel || found_rpath)
161     printf("%s\n", filename);
162    
163     bail:
164     unreadelf(elf);
165 solar 1.6 }
166    
167 solar 1.1 /* scan a directory for ET_EXEC files and print when we find one */
168 vapier 1.10 static void scanelf_dir(const char *path)
169 solar 1.1 {
170 vapier 1.10 register DIR *dir;
171     register struct dirent *dentry;
172     struct stat st;
173     char *p;
174     int len = 0;
175    
176     /* make sure path exists */
177     if (lstat(path, &st) == -1)
178     return;
179 solar 1.11
180 vapier 1.10 /* ok, if it isn't a directory, assume we can open it */
181     if (!S_ISDIR(st.st_mode)) {
182     scanelf_file(path);
183     return;
184     }
185    
186     /* now scan the dir looking for fun stuff */
187     if ((dir = opendir(path)) == NULL) {
188     warnf("could not opendir %s: %s", path, strerror(errno));
189     return;
190     }
191 solar 1.11
192 vapier 1.10 while ((dentry = readdir(dir))) {
193     if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
194     continue;
195     len = (strlen(path) + 2 + strlen(dentry->d_name));
196     p = malloc(len);
197     if (!p)
198     err("scanelf_dir(): Could not malloc: %s", strerror(errno));
199     strncpy(p, path, len);
200     strncat(p, "/", len);
201     strncat(p, dentry->d_name, len);
202     if (lstat(p, &st) != -1) {
203     if (S_ISREG(st.st_mode))
204     scanelf_file(p);
205     else if (dir_recurse && S_ISDIR(st.st_mode)) {
206     scanelf_dir(p);
207     }
208     }
209     free(p);
210     }
211     closedir(dir);
212 solar 1.1 }
213    
214 vapier 1.10 /* scan /etc/ld.so.conf for paths */
215     static void scanelf_ldpath()
216     {
217     char *path, *p;
218     FILE *fp;
219    
220     if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
221     err("Unable to open ld.so.conf: %s", strerror(errno));
222    
223     path = malloc(_POSIX_PATH_MAX);
224     while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
225     if (*path == '/') {
226     if ((p = strrchr(path, '\r')) != NULL)
227     *p = 0;
228     if ((p = strrchr(path, '\n')) != NULL)
229     *p = 0;
230     scanelf_dir(path);
231     }
232     free(path);
233    
234     fclose(fp);
235     }
236 solar 1.1
237 vapier 1.10 /* scan env PATH for paths */
238     static void scanelf_envpath()
239 solar 1.1 {
240 vapier 1.10 char *path, *p;
241    
242     path = getenv("PATH");
243     if (!path)
244     err("PATH is not set in your env !");
245    
246     if ((path = strdup(path)) == NULL)
247     err("stdup failed: %s", strerror(errno));
248    
249     while ((p = strrchr(path, ':')) != NULL) {
250     scanelf_dir(p + 1);
251     *p = 0;
252     }
253     free(path);
254 solar 1.1 }
255    
256    
257 vapier 1.10
258     /* usage / invocation handling functions */
259     #define PARSE_FLAGS "plRxstraqhV"
260     static struct option const long_opts[] = {
261     {"path", no_argument, NULL, 'p'},
262     {"ldpath", no_argument, NULL, 'l'},
263     {"recursive", no_argument, NULL, 'R'},
264     {"pax", no_argument, NULL, 'x'},
265     {"stack", no_argument, NULL, 's'},
266     {"textrel", no_argument, NULL, 't'},
267     {"rpath", no_argument, NULL, 'r'},
268     {"all", no_argument, NULL, 'a'},
269     {"quiet", no_argument, NULL, 'q'},
270     /* {"vebose", no_argument, NULL, 'v'},*/
271     {"help", no_argument, NULL, 'h'},
272     {"version", no_argument, NULL, 'V'},
273     {NULL, no_argument, NULL, 0x0}
274     };
275     static char *opts_help[] = {
276     "Scan all directories in PATH environment",
277     "Scan all directories in /etc/ld.so.conf",
278     "Scan directories recursively\n",
279     "Print PaX markings",
280     "Print GNU_STACK markings",
281     "Print TEXTREL information",
282     "Print RPATH information",
283     "Print all scanned info",
284     "Only output 'bad' things\n",
285     /* "Be verbose !",*/
286     "Print this help and exit",
287     "Print version and exit",
288     NULL
289     };
290    
291     /* display usage and exit */
292     static void usage(int status)
293 solar 1.1 {
294 vapier 1.10 int i;
295     printf(" Scan ELF binaries for stuff\n\n"
296     "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
297     printf("Options:\n");
298     for (i = 0; long_opts[i].name; ++i)
299     printf(" -%c, --%-12s %s\n", long_opts[i].val,
300     long_opts[i].name, opts_help[i]);
301     exit(status);
302 solar 1.1 }
303    
304     /* parse command line arguments and preform needed actions */
305 vapier 1.10 static void parseargs(int argc, char *argv[])
306     {
307     int flag;
308    
309     opterr = 0;
310     while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
311     switch (flag) {
312    
313     case 'V': /* version info */
314     printf("%s compiled %s\n"
315 solar 1.11 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n"
316 vapier 1.10 "%s\n",
317     __FILE__, __DATE__, argv0, rcsid);
318     exit(EXIT_SUCCESS);
319     break;
320     case 'h': usage(EXIT_SUCCESS); break;
321    
322     case 'l': scan_ldpath = 1; break;
323     case 'p': scan_envpath = 1; break;
324     case 'R': dir_recurse = 1; break;
325     case 'x': show_pax = 1; break;
326     case 's': show_stack = 1; break;
327     case 't': show_textrel = 1; break;
328     case 'r': show_rpath = 1; break;
329     case 'q': be_quiet = 1; break;
330     case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break;
331    
332     case ':':
333     warn("Option missing parameter");
334     usage(EXIT_FAILURE);
335     break;
336     case '?':
337     warn("Unknown option");
338     usage(EXIT_FAILURE);
339     break;
340     default:
341     err("Unhandled option '%c'", flag);
342     break;
343     }
344     }
345    
346     if (scan_ldpath) scanelf_ldpath();
347     if (scan_envpath) scanelf_envpath();
348     while (optind < argc)
349     scanelf_dir(argv[optind++]);
350     }
351    
352    
353    
354     int main(int argc, char *argv[])
355 solar 1.1 {
356 vapier 1.10 if (argc < 2)
357     usage(EXIT_FAILURE);
358     parseargs(argc, argv);
359     return EXIT_SUCCESS;
360 solar 1.1 }

  ViewVC Help
Powered by ViewVC 1.1.20