chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / elf / check-execstack.c
1 /* Check for executable stacks in DSOs.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contribute by Ulrich Drepper <drepper@redhat.com>. 2009.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <byteswap.h>
22 #include <elf.h>
23 #include <endian.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30
31 #ifdef BITS
32
33 # define AB(name) _AB (name, BITS)
34 # define _AB(name, bits) __AB (name, bits)
35 # define __AB(name, bits) name##bits
36 # define E(name) _E (name, BITS)
37 # define _E(name, bits) __E (name, bits)
38 # define __E(name, bits) Elf##bits##_##name
39 # define SWAP(val) \
40   ({ __typeof (val) __res;                                                    \
41      if (((ehdr.e_ident[EI_DATA] == ELFDATA2MSB                               \
42            && BYTE_ORDER == LITTLE_ENDIAN)                                    \
43           || (ehdr.e_ident[EI_DATA] == ELFDATA2LSB                            \
44               && BYTE_ORDER == BIG_ENDIAN))                                   \
45          && sizeof (val) != 1)                                                \
46        {                                                                      \
47          if (sizeof (val) == 2)                                               \
48            __res = bswap_16 (val);                                            \
49          else if (sizeof (val) == 4)                                          \
50            __res = bswap_32 (val);                                            \
51          else                                                                 \
52            __res = bswap_64 (val);                                            \
53        }                                                                      \
54      else                                                                     \
55        __res = (val);                                                         \
56      __res; })
57
58
59 static int
60 AB(handle_file) (const char *fname, int fd)
61 {
62   E(Ehdr) ehdr;
63
64   if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr))
65     {
66     read_error:
67       printf ("%s: read error: %m\n", fname);
68       return 1;
69     }
70
71   const size_t phnum = SWAP (ehdr.e_phnum);
72   const size_t phentsize = SWAP (ehdr.e_phentsize);
73
74   /* Read the program header.  */
75   E(Phdr) *phdr = alloca (phentsize * phnum);
76   if (pread (fd, phdr, phentsize * phnum, SWAP (ehdr.e_phoff))
77       != phentsize * phnum)
78     goto read_error;
79
80   /* Search for the PT_GNU_STACK entry.  */
81   for (size_t cnt = 0; cnt < phnum; ++cnt)
82     if (SWAP (phdr[cnt].p_type) == PT_GNU_STACK)
83       {
84         unsigned int flags = SWAP(phdr[cnt].p_flags);
85         if (flags & PF_X)
86           {
87             printf ("%s: executable stack signaled\n", fname);
88             return 1;
89           }
90
91         return 0;
92       }
93
94   printf ("%s: no PT_GNU_STACK entry\n", fname);
95   return 1;
96 }
97
98 # undef BITS
99 #else
100
101 # define BITS 32
102 # include "check-execstack.c"
103
104 # define BITS 64
105 # include "check-execstack.c"
106
107
108 static int
109 handle_file (const char *fname)
110 {
111   int fd = open (fname, O_RDONLY);
112   if (fd == -1)
113     {
114       printf ("cannot open %s: %m\n", fname);
115       return 1;
116     }
117
118   /* Read was is supposed to be the ELF header.  Read the initial
119      bytes to determine whether this is a 32 or 64 bit file.  */
120   char ident[EI_NIDENT];
121   if (read (fd, ident, EI_NIDENT) != EI_NIDENT)
122     {
123       printf ("%s: read error: %m\n", fname);
124       close (fd);
125       return 1;
126     }
127
128   if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
129     {
130       printf ("%s: not an ELF file\n", fname);
131       close (fd);
132       return 1;
133     }
134
135   int result;
136   if (ident[EI_CLASS] == ELFCLASS64)
137     result = handle_file64 (fname, fd);
138   else
139     result = handle_file32 (fname, fd);
140
141   close (fd);
142
143   return result;
144 }
145
146
147 int
148 main (int argc, char *argv[])
149 {
150   int cnt;
151   int result = 0;
152
153   for (cnt = 1; cnt < argc; ++cnt)
154     result |= handle_file (argv[cnt]);
155
156   return result;
157 }
158 #endif