]> git.pld-linux.org Git - packages/chpax.git/blob - chpax.c
- removed all Group fields translations (oure rpm now can handle translating
[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: 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
23 static struct elf32_hdr header_elf;
24 static struct exec header_aout;
25 static void *header;
26 static int header_size;
27 static int fd;
28
29 static unsigned long (*get_flags)();
30 static void (*put_flags)(unsigned long);
31
32 static unsigned long get_flags_elf()
33 {
34         return header_elf.e_flags;
35 }
36
37 static void put_flags_elf(unsigned long flags)
38 {
39         header_elf.e_flags = flags;
40 }
41
42 static unsigned long get_flags_aout()
43 {
44         return N_FLAGS(header_aout);
45 }
46
47 static void put_flags_aout(unsigned long flags)
48 {
49         N_SET_FLAGS(header_aout, flags & ~HF_PAX_RANDMMAP);
50 }
51
52 static 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
89 int 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
121 void usage(char *name)
122 {
123         printf(USAGE, name ? name : "chpax");
124         exit(1);
125 }
126
127 int 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.647034 seconds and 3 git commands to generate.