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

Contents of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (hide annotations) (download) (as text)
Wed Mar 30 23:43:30 2005 UTC (9 years, 9 months ago) by vapier
Branch: MAIN
Changes since 1.9: +305 -128 lines
File MIME type: text/x-csrc
fold pttool, scanexec, and scanrpath into scanelf and added ability to scan for TEXTRELs

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 vapier 1.10 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.9 2005/03/29 23:37:03 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 vapier 1.10 static const char *rcsid = "$Id: scanelf.c,v 1.9 2005/03/29 23:37:03 vapier Exp $";
37    
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     /* ok, if it isn't a directory, assume we can open it */
180     if (!S_ISDIR(st.st_mode)) {
181     scanelf_file(path);
182     return;
183     }
184    
185     /* now scan the dir looking for fun stuff */
186     if ((dir = opendir(path)) == NULL) {
187     warnf("could not opendir %s: %s", path, strerror(errno));
188     return;
189     }
190     while ((dentry = readdir(dir))) {
191     if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
192     continue;
193     len = (strlen(path) + 2 + strlen(dentry->d_name));
194     p = malloc(len);
195     if (!p)
196     err("scanelf_dir(): Could not malloc: %s", strerror(errno));
197     strncpy(p, path, len);
198     strncat(p, "/", len);
199     strncat(p, dentry->d_name, len);
200     if (lstat(p, &st) != -1) {
201     if (S_ISREG(st.st_mode))
202     scanelf_file(p);
203     else if (dir_recurse && S_ISDIR(st.st_mode)) {
204     scanelf_dir(p);
205     }
206     }
207     free(p);
208     }
209     closedir(dir);
210 solar 1.1 }
211    
212 vapier 1.10 /* scan /etc/ld.so.conf for paths */
213     static void scanelf_ldpath()
214     {
215     char *path, *p;
216     FILE *fp;
217    
218     if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
219     err("Unable to open ld.so.conf: %s", strerror(errno));
220    
221     path = malloc(_POSIX_PATH_MAX);
222     while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
223     if (*path == '/') {
224     if ((p = strrchr(path, '\r')) != NULL)
225     *p = 0;
226     if ((p = strrchr(path, '\n')) != NULL)
227     *p = 0;
228     scanelf_dir(path);
229     }
230     free(path);
231    
232     fclose(fp);
233     }
234 solar 1.1
235 vapier 1.10 /* scan env PATH for paths */
236     static void scanelf_envpath()
237 solar 1.1 {
238 vapier 1.10 char *path, *p;
239    
240     path = getenv("PATH");
241     if (!path)
242     err("PATH is not set in your env !");
243    
244     if ((path = strdup(path)) == NULL)
245     err("stdup failed: %s", strerror(errno));
246    
247     while ((p = strrchr(path, ':')) != NULL) {
248     scanelf_dir(p + 1);
249     *p = 0;
250     }
251     free(path);
252 solar 1.1 }
253    
254    
255 vapier 1.10
256     /* usage / invocation handling functions */
257     #define PARSE_FLAGS "plRxstraqhV"
258     static struct option const long_opts[] = {
259     {"path", no_argument, NULL, 'p'},
260     {"ldpath", no_argument, NULL, 'l'},
261     {"recursive", no_argument, NULL, 'R'},
262     {"pax", no_argument, NULL, 'x'},
263     {"stack", no_argument, NULL, 's'},
264     {"textrel", no_argument, NULL, 't'},
265     {"rpath", no_argument, NULL, 'r'},
266     {"all", no_argument, NULL, 'a'},
267     {"quiet", no_argument, NULL, 'q'},
268     /* {"vebose", no_argument, NULL, 'v'},*/
269     {"help", no_argument, NULL, 'h'},
270     {"version", no_argument, NULL, 'V'},
271     {NULL, no_argument, NULL, 0x0}
272     };
273     static char *opts_help[] = {
274     "Scan all directories in PATH environment",
275     "Scan all directories in /etc/ld.so.conf",
276     "Scan directories recursively\n",
277     "Print PaX markings",
278     "Print GNU_STACK markings",
279     "Print TEXTREL information",
280     "Print RPATH information",
281     "Print all scanned info",
282     "Only output 'bad' things\n",
283     /* "Be verbose !",*/
284     "Print this help and exit",
285     "Print version and exit",
286     NULL
287     };
288    
289     /* display usage and exit */
290     static void usage(int status)
291 solar 1.1 {
292 vapier 1.10 int i;
293     printf(" Scan ELF binaries for stuff\n\n"
294     "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
295     printf("Options:\n");
296     for (i = 0; long_opts[i].name; ++i)
297     printf(" -%c, --%-12s %s\n", long_opts[i].val,
298     long_opts[i].name, opts_help[i]);
299     exit(status);
300 solar 1.1 }
301    
302     /* parse command line arguments and preform needed actions */
303 vapier 1.10 static void parseargs(int argc, char *argv[])
304     {
305     int flag;
306    
307     opterr = 0;
308     while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
309     switch (flag) {
310    
311     case 'V': /* version info */
312     printf("%s compiled %s\n"
313     "%s written for Gentoo Linux by <solar@gentoo.org>\n"
314     "%s\n",
315     __FILE__, __DATE__, argv0, rcsid);
316     exit(EXIT_SUCCESS);
317     break;
318     case 'h': usage(EXIT_SUCCESS); break;
319    
320     case 'l': scan_ldpath = 1; break;
321     case 'p': scan_envpath = 1; break;
322     case 'R': dir_recurse = 1; break;
323     case 'x': show_pax = 1; break;
324     case 's': show_stack = 1; break;
325     case 't': show_textrel = 1; break;
326     case 'r': show_rpath = 1; break;
327     case 'q': be_quiet = 1; break;
328     case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break;
329    
330     case ':':
331     warn("Option missing parameter");
332     usage(EXIT_FAILURE);
333     break;
334     case '?':
335     warn("Unknown option");
336     usage(EXIT_FAILURE);
337     break;
338     default:
339     err("Unhandled option '%c'", flag);
340     break;
341     }
342     }
343    
344     if (scan_ldpath) scanelf_ldpath();
345     if (scan_envpath) scanelf_envpath();
346     while (optind < argc)
347     scanelf_dir(argv[optind++]);
348     }
349    
350    
351    
352     int main(int argc, char *argv[])
353 solar 1.1 {
354 vapier 1.10 if (argc < 2)
355     usage(EXIT_FAILURE);
356     parseargs(argc, argv);
357     return EXIT_SUCCESS;
358 solar 1.1 }

  ViewVC Help
Powered by ViewVC 1.1.20