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.
5 * Written by Solar Designer and placed in the public domain.
7 * Adapted to PaX by the PaX Team.
12 #include <sys/types.h>
15 #include <linux/elf.h>
16 #include <linux/a.out.h>
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 */
25 static struct elf32_hdr header_elf;
26 static struct exec header_aout;
28 static int header_size;
31 static unsigned long (*get_flags)();
32 static void (*put_flags)(unsigned long);
34 static unsigned long get_flags_elf()
36 return header_elf.e_flags;
39 static void put_flags_elf(unsigned long flags)
41 header_elf.e_flags = flags;
44 static unsigned long get_flags_aout()
46 return N_FLAGS(header_aout);
49 static void put_flags_aout(unsigned long flags)
51 N_SET_FLAGS(header_aout, flags & ~HF_PAX_RANDMMAP);
54 static int read_header(char *name, int mode)
59 if ((fd = open(name, mode)) < 0) return 1;
61 ptr = (char *)&header_elf;
62 size = sizeof(header_elf);
64 block = read(fd, ptr, size);
69 ptr += block; size -= block;
72 memcpy(&header_aout, &header_elf, sizeof(header_aout));
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;
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;
96 if (lseek(fd, 0, SEEK_SET)) return 1;
101 block = write(fd, ptr, size);
102 if (block <= 0) break;
103 ptr += block; size -= block;
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"
127 void usage(char *name)
129 printf(USAGE, name ? name : "chpax");
133 int main(int argc, char **argv)
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]);
146 mode = argv[1][1] == 'v' ? O_RDONLY : O_RDWR;
147 switch (read_header(*current, mode)) {
153 printf("%s: Unknown file type\n", *current);
157 printf("%s: Wrong architecture\n", *current);
163 switch (argv[1][1]) {
165 put_flags(flags | HF_PAX_PAGEEXEC);
169 put_flags((flags & ~HF_PAX_PAGEEXEC)|HF_PAX_SEGMEXEC);
173 put_flags(flags | HF_PAX_EMUTRAMP);
177 put_flags(flags & ~HF_PAX_EMUTRAMP);
181 put_flags(flags | HF_PAX_MPROTECT);
185 put_flags(flags & ~HF_PAX_MPROTECT);
189 put_flags(flags | HF_PAX_RANDMMAP);
193 put_flags(flags & ~HF_PAX_RANDMMAP);
197 put_flags(flags | HF_PAX_RANDEXEC);
201 put_flags(flags & ~HF_PAX_RANDEXEC);
205 put_flags(flags | HF_PAX_SEGMEXEC);
209 put_flags((flags & ~HF_PAX_SEGMEXEC)|HF_PAX_PAGEEXEC);
214 "paging based PAGE_EXEC is %s, "
215 "trampolines are %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");
234 if (flags != get_flags())
235 if (write_header()) {
241 } while (*++current);