]> git.pld-linux.org Git - packages/chpax.git/blob - chpax.c
- release 3: fixed %install: install also chstk.
[packages/chpax.git] / chpax.c
1 /*
2  * This program manages various PaX related flags for ELF and a.out binaries.
3  * The flags only have effect when running the patched Linux kernel.
4  *
5  * Written by Solar Designer and placed in the public domain.
6  *
7  * Adapted to PaX by the PaX Team.
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <linux/elf.h>
16 #include <linux/a.out.h>
17
18 #define HF_PAX_PAGEEXEC         1       /* 0: Paging based non-executable pages */
19 #define HF_PAX_EMUTRAMP         2       /* 0: Emulate trampolines */
20 #define HF_PAX_MPROTECT         4       /* 0: Restrict mprotect() */
21 #define HF_PAX_RANDMMAP         8       /* 0: Randomize mmap() base */
22 #define HF_PAX_RANDEXEC         16      /* 1: Randomize ET_EXEC base */
23 #define HF_PAX_SEGMEXEC         32      /* 0: Segmentation based non-executable pages */
24
25 static struct elf32_hdr header_elf;
26 static struct exec header_aout;
27 static void *header;
28 static int header_size;
29 static int fd;
30
31 static unsigned long (*get_flags)();
32 static void (*put_flags)(unsigned long);
33
34 static unsigned long get_flags_elf()
35 {
36         return header_elf.e_flags;
37 }
38
39 static void put_flags_elf(unsigned long flags)
40 {
41         header_elf.e_flags = flags;
42 }
43
44 static unsigned long get_flags_aout()
45 {
46         return N_FLAGS(header_aout);
47 }
48
49 static void put_flags_aout(unsigned long flags)
50 {
51         N_SET_FLAGS(header_aout, flags & ~HF_PAX_RANDMMAP);
52 }
53
54 static int read_header(char *name, int mode)
55 {
56         char *ptr;
57         int size, block;
58
59         if ((fd = open(name, mode)) < 0) return 1;
60
61         ptr = (char *)&header_elf;
62         size = sizeof(header_elf);
63         do {
64                 block = read(fd, ptr, size);
65                 if (block <= 0) {
66                         close(fd);
67                         return block ? 1 : 2;
68                 }
69                 ptr += block; size -= block;
70         } while (size > 0);
71
72         memcpy(&header_aout, &header_elf, sizeof(header_aout));
73
74         if (!strncmp(header_elf.e_ident, ELFMAG, SELFMAG)) {
75                 if (header_elf.e_type != ET_EXEC && header_elf.e_type != ET_DYN) return 2;
76                 if (header_elf.e_machine != EM_386) return 3;
77                 header = &header_elf; header_size = sizeof(header_elf);
78                 get_flags = get_flags_elf; put_flags = put_flags_elf;
79         } else
80         if (N_MAGIC(header_aout) == NMAGIC ||
81             N_MAGIC(header_aout) == ZMAGIC ||
82             N_MAGIC(header_aout) == QMAGIC) {
83                 if (N_MACHTYPE(header_aout) != M_386) return 3;
84                 header = &header_aout; header_size = 4;
85                 get_flags = get_flags_aout; put_flags = put_flags_aout;
86         } else return 2;
87
88         return 0;
89 }
90
91 int write_header()
92 {
93         char *ptr;
94         int size, block;
95
96         if (lseek(fd, 0, SEEK_SET)) return 1;
97
98         ptr = (char *)header;
99         size = header_size;
100         do {
101                 block = write(fd, ptr, size);
102                 if (block <= 0) break;
103                 ptr += block; size -= block;
104         } while (size > 0);
105
106         return size;
107 }
108
109 #define USAGE \
110 "Usage: %s OPTIONS FILE...\n" \
111 "Manage PaX flags for binaries\n\n" \
112 "  -P\tenforce paging based non-executable pages\n" \
113 "  -p\tdo not enforce paging based non-executable pages\n" \
114 "  -E\temulate trampolines\n" \
115 "  -e\tdo not emulate trampolines\n" \
116 "  -M\trestrict mprotect()\n" \
117 "  -m\tdo not restrict mprotect()\n" \
118 "  -R\trandomize mmap() base [ELF only]\n" \
119 "  -r\tdo not randomize mmap() base [ELF only]\n" \
120 "  -X\trandomize ET_EXEC base [ELF only]\n" \
121 "  -x\tdo not randomize ET_EXEC base [ELF only]\n" \
122 "  -S\tenforce segmentation based non-executable pages\n" \
123 "  -s\tdo not enforce segmentation based non-executable pages\n" \
124 "  -v\tview current flag state\n\n" \
125 "The flags only have effect when running the patched Linux kernel.\n"
126
127 void usage(char *name)
128 {
129         printf(USAGE, name ? name : "chpax");
130         exit(1);
131 }
132
133 int main(int argc, char **argv)
134 {
135         char **current;
136         unsigned long flags;
137         int error = 0;
138         int mode;
139
140         if (argc < 3) usage(argv[0]);
141         if (strlen(argv[1]) != 2) usage(argv[0]);
142         if (argv[1][0] != '-' || !strchr("pPeEmMrRxXsSv", argv[1][1])) usage(argv[0]);
143
144         current = &argv[2];
145         do {
146                 mode = argv[1][1] == 'v' ? O_RDONLY : O_RDWR;
147                 switch (read_header(*current, mode)) {
148                 case 1:
149                         perror(*current);
150                         error = 1; continue;
151
152                 case 2:
153                         printf("%s: Unknown file type\n", *current);
154                         error = 1; continue;
155
156                 case 3:
157                         printf("%s: Wrong architecture\n", *current);
158                         error = 1; continue;
159                 }
160
161                 flags = get_flags();
162
163                 switch (argv[1][1]) {
164                 case 'p':
165                         put_flags(flags | HF_PAX_PAGEEXEC);
166                         break;
167
168                 case 'P':
169                         put_flags((flags & ~HF_PAX_PAGEEXEC)|HF_PAX_SEGMEXEC);
170                         break;
171
172                 case 'E':
173                         put_flags(flags | HF_PAX_EMUTRAMP);
174                         break;
175
176                 case 'e':
177                         put_flags(flags & ~HF_PAX_EMUTRAMP);
178                         break;
179
180                 case 'm':
181                         put_flags(flags | HF_PAX_MPROTECT);
182                         break;
183
184                 case 'M':
185                         put_flags(flags & ~HF_PAX_MPROTECT);
186                         break;
187
188                 case 'r':
189                         put_flags(flags | HF_PAX_RANDMMAP);
190                         break;
191
192                 case 'R':
193                         put_flags(flags & ~HF_PAX_RANDMMAP);
194                         break;
195
196                 case 'X':
197                         put_flags(flags | HF_PAX_RANDEXEC);
198                         break;
199
200                 case 'x':
201                         put_flags(flags & ~HF_PAX_RANDEXEC);
202                         break;
203
204                 case 's':
205                         put_flags(flags | HF_PAX_SEGMEXEC);
206                         break;
207
208                 case 'S':
209                         put_flags((flags & ~HF_PAX_SEGMEXEC)|HF_PAX_PAGEEXEC);
210                         break;
211
212                 default:
213                         printf("%s: "
214                                "paging based PAGE_EXEC is %s, "
215                                "trampolines are %s, "
216                                "mprotect() is %s, "
217                                "mmap() base is %s, "
218                                "ET_EXEC base is %s, "
219                                "segmentation based PAGE_EXEC is %s\n", *current,
220                                 (flags & HF_PAX_PAGEEXEC) || !(flags & HF_PAX_SEGMEXEC)
221                                 ? "disabled" : "enabled",
222                                 flags & HF_PAX_EMUTRAMP
223                                 ? "emulated" : "not emulated",
224                                 flags & HF_PAX_MPROTECT
225                                 ? "not restricted" : "restricted",
226                                 flags & HF_PAX_RANDMMAP
227                                 ? "not randomized" : "randomized",
228                                 flags & HF_PAX_RANDEXEC
229                                 ? "randomized" : "not randomized",
230                                 flags & HF_PAX_SEGMEXEC
231                                 ? "disabled" : "enabled");
232                 }
233
234                 if (flags != get_flags())
235                 if (write_header()) {
236                         perror(*current);
237                         error = 1;
238                 }
239
240                 close(fd);
241         } while (*++current);
242
243         return error;
244 }
This page took 0.058201 seconds and 3 git commands to generate.