]> git.pld-linux.org Git - packages/chpax.git/blame - chpax.c
- removed all Group fields translations (oure rpm now can handle translating
[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
18#define HF_PAX_PAGEEXEC 1 /* 0: Enforce PAGE_EXEC */
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
23static struct elf32_hdr header_elf;
24static struct exec header_aout;
25static void *header;
26static int header_size;
27static int fd;
28
29static unsigned long (*get_flags)();
30static void (*put_flags)(unsigned long);
31
32static unsigned long get_flags_elf()
33{
34 return header_elf.e_flags;
35}
36
37static void put_flags_elf(unsigned long flags)
38{
39 header_elf.e_flags = flags;
40}
41
42static unsigned long get_flags_aout()
43{
44 return N_FLAGS(header_aout);
45}
46
47static void put_flags_aout(unsigned long flags)
48{
49 N_SET_FLAGS(header_aout, flags & ~HF_PAX_RANDMMAP);
50}
51
52static int read_header(char *name, int mode)
53{
54 char *ptr;
55 int size, block;
56
57 if ((fd = open(name, mode)) < 0) return 1;
58
59 ptr = (char *)&header_elf;
60 size = sizeof(header_elf);
61 do {
62 block = read(fd, ptr, size);
63 if (block <= 0) {
64 close(fd);
65 return block ? 1 : 2;
66 }
67 ptr += block; size -= block;
68 } while (size > 0);
69
70 memcpy(&header_aout, &header_elf, sizeof(header_aout));
71
72 if (!strncmp(header_elf.e_ident, ELFMAG, SELFMAG)) {
73 if (header_elf.e_type != ET_EXEC && header_elf.e_type != ET_DYN) return 2;
74 if (header_elf.e_machine != EM_386) return 3;
75 header = &header_elf; header_size = sizeof(header_elf);
76 get_flags = get_flags_elf; put_flags = put_flags_elf;
77 } else
78 if (N_MAGIC(header_aout) == NMAGIC ||
79 N_MAGIC(header_aout) == ZMAGIC ||
80 N_MAGIC(header_aout) == QMAGIC) {
81 if (N_MACHTYPE(header_aout) != M_386) return 3;
82 header = &header_aout; header_size = 4;
83 get_flags = get_flags_aout; put_flags = put_flags_aout;
84 } else return 2;
85
86 return 0;
87}
88
89int write_header()
90{
91 char *ptr;
92 int size, block;
93
94 if (lseek(fd, 0, SEEK_SET)) return 1;
95
96 ptr = (char *)header;
97 size = header_size;
98 do {
99 block = write(fd, ptr, size);
100 if (block <= 0) break;
101 ptr += block; size -= block;
102 } while (size > 0);
103
104 return size;
105}
106
107#define USAGE \
108"Usage: %s OPTIONS FILE...\n" \
109"Manage PaX flags for binaries\n\n" \
110" -P\tenforce PAGE_EXEC\n" \
111" -p\tdo not enforce PAGE_EXEC\n" \
112" -E\temulate trampolines\n" \
113" -e\tdo not emulate trampolines\n" \
114" -M\trestrict mprotect()\n" \
115" -m\tdo not restrict mprotect()\n" \
116" -R\trandomize mmap() base [ELF only]\n" \
117" -r\tdo not randomize mmap() base [ELF only]\n" \
118" -v\tview current flag state\n\n" \
119"The flags only have effect when running the patched Linux kernel.\n"
120
121void usage(char *name)
122{
123 printf(USAGE, name ? name : "chpax");
124 exit(1);
125}
126
127int main(int argc, char **argv)
128{
129 char **current;
130 unsigned long flags;
131 int error = 0;
132 int mode;
133
134 if (argc < 3) usage(argv[0]);
135 if (strlen(argv[1]) != 2) usage(argv[0]);
136 if (argv[1][0] != '-' || !strchr("pPeEmMrRv", argv[1][1])) usage(argv[0]);
137
138 current = &argv[2];
139 do {
140 mode = argv[1][1] == 'v' ? O_RDONLY : O_RDWR;
141 switch (read_header(*current, mode)) {
142 case 1:
143 perror(*current);
144 error = 1; continue;
145
146 case 2:
147 printf("%s: Unknown file type\n", *current);
148 error = 1; continue;
149
150 case 3:
151 printf("%s: Wrong architecture\n", *current);
152 error = 1; continue;
153 }
154
155 flags = get_flags();
156
157 switch (argv[1][1]) {
158 case 'p':
159 put_flags(flags | HF_PAX_PAGEEXEC);
160 break;
161
162 case 'P':
163 put_flags(flags & ~HF_PAX_PAGEEXEC);
164 break;
165
166 case 'E':
167 put_flags(flags | HF_PAX_EMUTRAMP);
168 break;
169
170 case 'e':
171 put_flags(flags & ~HF_PAX_EMUTRAMP);
172 break;
173
174 case 'm':
175 put_flags(flags | HF_PAX_MPROTECT);
176 break;
177
178 case 'M':
179 put_flags(flags & ~HF_PAX_MPROTECT);
180 break;
181
182 case 'r':
183 put_flags(flags | HF_PAX_RANDMMAP);
184 break;
185
186 case 'R':
187 put_flags(flags & ~HF_PAX_RANDMMAP);
188 break;
189
190 default:
191 printf("%s: "
192 "PAGE_EXEC is %s, "
193 "trampolines are %s, "
194 "mprotect() is %s, "
195 "mmap() base is %s\n", *current,
196 flags & HF_PAX_PAGEEXEC
197 ? "disabled" : "enabled",
198 flags & HF_PAX_EMUTRAMP
199 ? "emulated" : "not emulated",
200 flags & HF_PAX_MPROTECT
201 ? "not restricted" : "restricted",
202 flags & HF_PAX_RANDMMAP
203 ? "not randomized" : "randomized");
204 }
205
206 if (flags != get_flags())
207 if (write_header()) {
208 perror(*current);
209 error = 1;
210 }
211
212 close(fd);
213 } while (*++current);
214
215 return error;
216}
This page took 0.532724 seconds and 4 git commands to generate.