]> git.pld-linux.org Git - packages/chpax.git/blame - chpax.c
- release 3: fixed %install: install also chstk.
[packages/chpax.git] / chpax.c
CommitLineData
450271d5
AM
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
3fd0ba6c 18#define HF_PAX_PAGEEXEC 1 /* 0: Paging based non-executable pages */
450271d5
AM
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 */
3fd0ba6c
PG
22#define HF_PAX_RANDEXEC 16 /* 1: Randomize ET_EXEC base */
23#define HF_PAX_SEGMEXEC 32 /* 0: Segmentation based non-executable pages */
450271d5
AM
24
25static struct elf32_hdr header_elf;
26static struct exec header_aout;
27static void *header;
28static int header_size;
29static int fd;
30
31static unsigned long (*get_flags)();
32static void (*put_flags)(unsigned long);
33
34static unsigned long get_flags_elf()
35{
36 return header_elf.e_flags;
37}
38
39static void put_flags_elf(unsigned long flags)
40{
41 header_elf.e_flags = flags;
42}
43
44static unsigned long get_flags_aout()
45{
46 return N_FLAGS(header_aout);
47}
48
49static void put_flags_aout(unsigned long flags)
50{
51 N_SET_FLAGS(header_aout, flags & ~HF_PAX_RANDMMAP);
52}
53
54static 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
91int 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" \
3fd0ba6c
PG
112" -P\tenforce paging based non-executable pages\n" \
113" -p\tdo not enforce paging based non-executable pages\n" \
450271d5
AM
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" \
3fd0ba6c
PG
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" \
450271d5
AM
124" -v\tview current flag state\n\n" \
125"The flags only have effect when running the patched Linux kernel.\n"
126
127void usage(char *name)
128{
129 printf(USAGE, name ? name : "chpax");
130 exit(1);
131}
132
133int 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]);
3fd0ba6c 142 if (argv[1][0] != '-' || !strchr("pPeEmMrRxXsSv", argv[1][1])) usage(argv[0]);
450271d5
AM
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':
3fd0ba6c 169 put_flags((flags & ~HF_PAX_PAGEEXEC)|HF_PAX_SEGMEXEC);
450271d5
AM
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
3fd0ba6c
PG
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
450271d5
AM
212 default:
213 printf("%s: "
3fd0ba6c 214 "paging based PAGE_EXEC is %s, "
450271d5
AM
215 "trampolines are %s, "
216 "mprotect() is %s, "
3fd0ba6c
PG
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)
450271d5
AM
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
3fd0ba6c
PG
227 ? "not randomized" : "randomized",
228 flags & HF_PAX_RANDEXEC
229 ? "randomized" : "not randomized",
230 flags & HF_PAX_SEGMEXEC
231 ? "disabled" : "enabled");
450271d5
AM
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.100103 seconds and 4 git commands to generate.