| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: paxctl.c,v 1.10 2009/05/02 06:01:30 elad Exp $ */ | | 1 | /* $NetBSD: paxctl.c,v 1.11 2009/05/02 16:19:36 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> | | 4 | * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> |
5 | * Copyright (c) 2008 Christos Zoulas <christos@NetBSD.org> | | 5 | * Copyright (c) 2008 Christos Zoulas <christos@NetBSD.org> |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -24,27 +24,27 @@ | | | @@ -24,27 +24,27 @@ |
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | #if HAVE_NBTOOL_CONFIG_H | | 30 | #if HAVE_NBTOOL_CONFIG_H |
31 | #include "nbtool_config.h" | | 31 | #include "nbtool_config.h" |
32 | #endif | | 32 | #endif |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | #ifndef lint | | 35 | #ifndef lint |
36 | #ifdef __RCSID | | 36 | #ifdef __RCSID |
37 | __RCSID("$NetBSD: paxctl.c,v 1.10 2009/05/02 06:01:30 elad Exp $"); | | 37 | __RCSID("$NetBSD: paxctl.c,v 1.11 2009/05/02 16:19:36 christos Exp $"); |
38 | #endif | | 38 | #endif |
39 | #endif /* not lint */ | | 39 | #endif /* not lint */ |
40 | | | 40 | |
41 | #include <sys/types.h> | | 41 | #include <sys/types.h> |
42 | #ifdef HAVE_NBTOOL_CONFIG_H | | 42 | #ifdef HAVE_NBTOOL_CONFIG_H |
43 | #include "../../sys/sys/exec_elf.h" | | 43 | #include "../../sys/sys/exec_elf.h" |
44 | #else | | 44 | #else |
45 | #include <elf.h> | | 45 | #include <elf.h> |
46 | #endif | | 46 | #endif |
47 | #include <stdio.h> | | 47 | #include <stdio.h> |
48 | #include <err.h> | | 48 | #include <err.h> |
49 | #include <fcntl.h> | | 49 | #include <fcntl.h> |
50 | #include <unistd.h> | | 50 | #include <unistd.h> |
| @@ -183,151 +183,142 @@ process_one(const char *name, uint32_t a | | | @@ -183,151 +183,142 @@ process_one(const char *name, uint32_t a |
183 | /*LINTED*/(sizeof(a) == 1 ? (a) : \ | | 183 | /*LINTED*/(sizeof(a) == 1 ? (a) : \ |
184 | /*LINTED*/(sizeof(a) == 2 ? bswap16(a) : \ | | 184 | /*LINTED*/(sizeof(a) == 2 ? bswap16(a) : \ |
185 | /*LINTED*/(sizeof(a) == 4 ? bswap32(a) : \ | | 185 | /*LINTED*/(sizeof(a) == 4 ? bswap32(a) : \ |
186 | /*LINTED*/(sizeof(a) == 8 ? bswap64(a) : (abort(), (a))))))) | | 186 | /*LINTED*/(sizeof(a) == 8 ? bswap64(a) : (abort(), (a))))))) |
187 | #define EH(field) (size == 32 ? SWAP(e.h32.field) : SWAP(e.h64.field)) | | 187 | #define EH(field) (size == 32 ? SWAP(e.h32.field) : SWAP(e.h64.field)) |
188 | #define PH(field) (size == 32 ? SWAP(p.h32.field) : SWAP(p.h64.field)) | | 188 | #define PH(field) (size == 32 ? SWAP(p.h32.field) : SWAP(p.h64.field)) |
189 | #define NH(field) (size == 32 ? SWAP(n.h32.field) : SWAP(n.h64.field)) | | 189 | #define NH(field) (size == 32 ? SWAP(n.h32.field) : SWAP(n.h64.field)) |
190 | #define PHSIZE (size == 32 ? sizeof(p.h32) : sizeof(p.h64)) | | 190 | #define PHSIZE (size == 32 ? sizeof(p.h32) : sizeof(p.h64)) |
191 | #define NHSIZE (size == 32 ? sizeof(n.h32) : sizeof(n.h64)) | | 191 | #define NHSIZE (size == 32 ? sizeof(n.h32) : sizeof(n.h64)) |
192 | struct { | | 192 | struct { |
193 | char name[ELF_NOTE_PAX_NAMESZ]; | | 193 | char name[ELF_NOTE_PAX_NAMESZ]; |
194 | uint32_t flags; | | 194 | uint32_t flags; |
195 | } pax_tag; | | 195 | } pax_tag; |
196 | int fd, size, ok = 0, flagged = 0, swap; | | 196 | int fd, size, ok = 0, flagged = 0, swap, error = 1; |
197 | size_t i; | | 197 | size_t i; |
198 | | | 198 | |
199 | fd = open(name, list ? O_RDONLY: O_RDWR, 0); | | 199 | fd = open(name, list ? O_RDONLY: O_RDWR, 0); |
200 | if (fd == -1) { | | 200 | if (fd == -1) { |
201 | warn("Can't open `%s'", name); | | 201 | warn("Can't open `%s'", name); |
202 | return 1; | | 202 | return error; |
203 | } | | 203 | } |
204 | | | 204 | |
205 | if (read(fd, &e, sizeof(e)) != sizeof(e)) { | | 205 | if (read(fd, &e, sizeof(e)) != sizeof(e)) { |
206 | warn("Can't read ELF header from `%s'", name); | | 206 | warn("Can't read ELF header from `%s'", name); |
207 | (void)close(fd); | | 207 | goto out; |
208 | return 1; | | | |
209 | } | | 208 | } |
210 | | | 209 | |
211 | if (memcmp(e.h32.e_ident, ELFMAG, SELFMAG) != 0) { | | 210 | if (memcmp(e.h32.e_ident, ELFMAG, SELFMAG) != 0) { |
212 | warnx("Bad ELF magic from `%s' (maybe it's not an ELF?)", name); | | 211 | warnx("Bad ELF magic from `%s' (maybe it's not an ELF?)", name); |
213 | (void)close(fd); | | 212 | goto out; |
214 | return 1; | | | |
215 | } | | 213 | } |
216 | | | 214 | |
217 | if (e.h32.e_ehsize == sizeof(e.h32)) { | | 215 | if (e.h32.e_ehsize == sizeof(e.h32)) { |
218 | size = 32; | | 216 | size = 32; |
219 | swap = 0; | | 217 | swap = 0; |
220 | } else if (e.h64.e_ehsize == sizeof(e.h64)) { | | 218 | } else if (e.h64.e_ehsize == sizeof(e.h64)) { |
221 | size = 64; | | 219 | size = 64; |
222 | swap = 0; | | 220 | swap = 0; |
223 | } else if (bswap16(e.h32.e_ehsize) == sizeof(e.h32)) { | | 221 | } else if (bswap16(e.h32.e_ehsize) == sizeof(e.h32)) { |
224 | size = 32; | | 222 | size = 32; |
225 | swap = 1; | | 223 | swap = 1; |
226 | } else if (bswap16(e.h64.e_ehsize) == sizeof(e.h64)) { | | 224 | } else if (bswap16(e.h64.e_ehsize) == sizeof(e.h64)) { |
227 | size = 64; | | 225 | size = 64; |
228 | swap = 1; | | 226 | swap = 1; |
229 | } else { | | 227 | } else { |
230 | warnx("Bad ELF size %d from `%s' (maybe it's not an ELF?)", | | 228 | warnx("Bad ELF size %d from `%s' (maybe it's not an ELF?)", |
231 | (int)e.h32.e_ehsize, name); | | 229 | (int)e.h32.e_ehsize, name); |
232 | (void)close(fd); | | 230 | goto out; |
233 | return 1; | | | |
234 | } | | 231 | } |
235 | | | 232 | |
236 | for (i = 0; i < EH(e_phnum); i++) { | | 233 | for (i = 0; i < EH(e_phnum); i++) { |
237 | if ((size_t)pread(fd, &p, PHSIZE, (off_t)EH(e_phoff) + i * PHSIZE) != | | 234 | if ((size_t)pread(fd, &p, PHSIZE, |
238 | PHSIZE) { | | 235 | (off_t)EH(e_phoff) + i * PHSIZE) != PHSIZE) { |
239 | warn("Can't read program header data from `%s'", name); | | 236 | warn("Can't read program header data from `%s'", name); |
240 | (void)close(fd); | | 237 | goto out; |
241 | return 1; | | | |
242 | } | | 238 | } |
243 | | | 239 | |
244 | if (PH(p_type) != PT_NOTE) | | 240 | if (PH(p_type) != PT_NOTE) |
245 | continue; | | 241 | continue; |
246 | | | 242 | |
247 | if (pread(fd, &n, NHSIZE, (off_t)PH(p_offset)) != NHSIZE) { | | 243 | if (pread(fd, &n, NHSIZE, (off_t)PH(p_offset)) != NHSIZE) { |
248 | warn("Can't read note header from `%s'", name); | | 244 | warn("Can't read note header from `%s'", name); |
249 | (void)close(fd); | | 245 | goto out; |
250 | return 1; | | | |
251 | } | | 246 | } |
252 | if (NH(n_type) != ELF_NOTE_TYPE_PAX_TAG || | | 247 | if (NH(n_type) != ELF_NOTE_TYPE_PAX_TAG || |
253 | NH(n_descsz) != ELF_NOTE_PAX_DESCSZ || | | 248 | NH(n_descsz) != ELF_NOTE_PAX_DESCSZ || |
254 | NH(n_namesz) != ELF_NOTE_PAX_NAMESZ) | | 249 | NH(n_namesz) != ELF_NOTE_PAX_NAMESZ) |
255 | continue; | | 250 | continue; |
256 | if (pread(fd, &pax_tag, sizeof(pax_tag), PH(p_offset) + NHSIZE) | | 251 | if (pread(fd, &pax_tag, sizeof(pax_tag), PH(p_offset) + NHSIZE) |
257 | != sizeof(pax_tag)) { | | 252 | != sizeof(pax_tag)) { |
258 | warn("Can't read pax_tag from `%s'", name); | | 253 | warn("Can't read pax_tag from `%s'", name); |
259 | (void)close(fd); | | 254 | goto out; |
260 | return 1; | | | |
261 | } | | 255 | } |
262 | if (memcmp(pax_tag.name, ELF_NOTE_PAX_NAME, | | 256 | if (memcmp(pax_tag.name, ELF_NOTE_PAX_NAME, |
263 | sizeof(pax_tag.name)) != 0) { | | 257 | sizeof(pax_tag.name)) != 0) { |
264 | warn("Unknown pax_tag name `%*.*s' from `%s'", | | 258 | warn("Unknown pax_tag name `%*.*s' from `%s'", |
265 | ELF_NOTE_PAX_NAMESZ, ELF_NOTE_PAX_NAMESZ, | | 259 | ELF_NOTE_PAX_NAMESZ, ELF_NOTE_PAX_NAMESZ, |
266 | pax_tag.name, name); | | 260 | pax_tag.name, name); |
267 | (void)close(fd); | | 261 | goto out; |
268 | return 1; | | | |
269 | } | | 262 | } |
270 | ok = 1; | | 263 | ok = 1; |
271 | | | 264 | |
272 | if (list) { | | 265 | if (list) { |
273 | if (!pax_haveflags(SWAP(pax_tag.flags))) | | 266 | if (!pax_haveflags(SWAP(pax_tag.flags))) |
274 | break; | | 267 | break; |
275 | | | 268 | |
276 | if (!pax_flags_sane(SWAP(pax_tag.flags))) | | 269 | if (!pax_flags_sane(SWAP(pax_tag.flags))) |
277 | warnx("Current flags 0x%x don't make sense", | | 270 | warnx("Current flags 0x%x don't make sense", |
278 | (uint32_t)SWAP(pax_tag.flags)); | | 271 | (uint32_t)SWAP(pax_tag.flags)); |
279 | | | 272 | |
280 | if (many) | | 273 | if (many) |
281 | (void)printf("%s: ", name); | | 274 | (void)printf("%s: ", name); |
282 | (void)printf("PaX flags:\n"); | | 275 | (void)printf("PaX flags:\n"); |
283 | | | 276 | |
284 | pax_printflags(name, many, SWAP(pax_tag.flags)); | | 277 | pax_printflags(name, many, SWAP(pax_tag.flags)); |
285 | | | | |
286 | flagged = 1; | | 278 | flagged = 1; |
287 | | | | |
288 | break; | | 279 | break; |
289 | } | | 280 | } |
290 | | | 281 | |
291 | pax_tag.flags |= SWAP(add_flags); | | 282 | pax_tag.flags |= SWAP(add_flags); |
292 | pax_tag.flags &= SWAP(~del_flags); | | 283 | pax_tag.flags &= SWAP(~del_flags); |
293 | | | 284 | |
294 | if (!pax_flags_sane(SWAP(pax_tag.flags))) { | | 285 | if (!pax_flags_sane(SWAP(pax_tag.flags))) { |
295 | warnx("New flags 0x%x don't make sense", | | 286 | warnx("New flags 0x%x don't make sense", |
296 | (uint32_t)SWAP(pax_tag.flags)); | | 287 | (uint32_t)SWAP(pax_tag.flags)); |
297 | (void)close(fd); | | 288 | goto out; |
298 | return 1; | | | |
299 | } | | 289 | } |
300 | | | 290 | |
301 | if (pwrite(fd, &pax_tag, sizeof(pax_tag), | | 291 | if (pwrite(fd, &pax_tag, sizeof(pax_tag), |
302 | (off_t)PH(p_offset) + NHSIZE) != sizeof(pax_tag)) | | 292 | (off_t)PH(p_offset) + NHSIZE) != sizeof(pax_tag)) |
303 | warn("Can't modify flags on `%s'", name); | | 293 | warn("Can't modify flags on `%s'", name); |
304 | break; | | 294 | break; |
305 | } | | 295 | } |
306 | | | 296 | |
307 | (void)close(fd); | | | |
308 | | | | |
309 | if (!ok) { | | 297 | if (!ok) { |
310 | warnx("Could not find an ELF PaX PT_NOTE section in `%s'", | | 298 | warnx("Could not find an ELF PaX PT_NOTE section in `%s'", |
311 | name); | | 299 | name); |
312 | return 1; | | 300 | goto out; |
313 | } | | 301 | } |
314 | | | 302 | |
| | | 303 | error = 0; |
315 | if (list && !flagged) { | | 304 | if (list && !flagged) { |
316 | if (many) | | 305 | if (many) |
317 | (void)printf("%s: ", name); | | 306 | (void)printf("%s: ", name); |
318 | (void)printf("No PaX flags.\n"); | | 307 | (void)printf("No PaX flags.\n"); |
319 | } | | 308 | } |
320 | return 0; | | 309 | out: |
| | | 310 | (void)close(fd); |
| | | 311 | return error; |
321 | } | | 312 | } |
322 | | | 313 | |
323 | int | | 314 | int |
324 | main(int argc, char **argv) | | 315 | main(int argc, char **argv) |
325 | { | | 316 | { |
326 | char *opt; | | 317 | char *opt; |
327 | int i, list = 0, bad = 0, many, minus; | | 318 | int i, list = 0, bad = 0, many, minus; |
328 | uint32_t add_flags = 0, del_flags = 0; | | 319 | uint32_t add_flags = 0, del_flags = 0; |
329 | | | 320 | |
330 | setprogname(argv[0]); | | 321 | setprogname(argv[0]); |
331 | | | 322 | |
332 | if (argc < 2) | | 323 | if (argc < 2) |
333 | usage(); | | 324 | usage(); |