aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
authorAndrew Morton <akpm@linux-foundation.org>2007-07-21 07:37:32 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-21 20:49:14 -0400
commitd4e3cc387ea1b74c3ad2ef2f6f5c05fd6fc314b8 (patch)
treeb14dde552be76614fe443eccbb15658f651fc36c /fs/binfmt_elf.c
parent80e27982a66ea8306a704ba8bdf634ed480d4b46 (diff)
revert "PIE randomization"
There are reports of this causing userspace failures (http://lkml.org/lkml/2007/7/20/421). Revert. Cc: Jan Kratochvil <honza@jikos.cz> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Ingo Molnar <mingo@elte.hu> Cc: Roland McGrath <roland@redhat.com> Cc: Jakub Jelinek <jakub@redhat.com> Cc: Ulrich Kunitz <kune@deine-taler.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: "Bret Towe" <magnade@gmail.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c109
1 files changed, 23 insertions, 86 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ba24cb2ff6ce..4482a0673b15 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -45,7 +45,7 @@
45 45
46static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); 46static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
47static int load_elf_library(struct file *); 47static int load_elf_library(struct file *);
48static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long); 48static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
49 49
50/* 50/*
51 * If we don't support core dumping, then supply a NULL so we 51 * If we don't support core dumping, then supply a NULL so we
@@ -80,7 +80,7 @@ static struct linux_binfmt elf_format = {
80 .hasvdso = 1 80 .hasvdso = 1
81}; 81};
82 82
83#define BAD_ADDR(x) IS_ERR_VALUE(x) 83#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
84 84
85static int set_brk(unsigned long start, unsigned long end) 85static int set_brk(unsigned long start, unsigned long end)
86{ 86{
@@ -295,70 +295,33 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
295#ifndef elf_map 295#ifndef elf_map
296 296
297static unsigned long elf_map(struct file *filep, unsigned long addr, 297static unsigned long elf_map(struct file *filep, unsigned long addr,
298 struct elf_phdr *eppnt, int prot, int type, 298 struct elf_phdr *eppnt, int prot, int type)
299 unsigned long total_size)
300{ 299{
301 unsigned long map_addr; 300 unsigned long map_addr;
302 unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); 301 unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
303 unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
304 addr = ELF_PAGESTART(addr);
305 size = ELF_PAGEALIGN(size);
306 302
303 down_write(&current->mm->mmap_sem);
307 /* mmap() will return -EINVAL if given a zero size, but a 304 /* mmap() will return -EINVAL if given a zero size, but a
308 * segment with zero filesize is perfectly valid */ 305 * segment with zero filesize is perfectly valid */
309 if (!size) 306 if (eppnt->p_filesz + pageoffset)
310 return addr; 307 map_addr = do_mmap(filep, ELF_PAGESTART(addr),
311 308 eppnt->p_filesz + pageoffset, prot, type,
312 down_write(&current->mm->mmap_sem); 309 eppnt->p_offset - pageoffset);
313 /* 310 else
314 * total_size is the size of the ELF (interpreter) image. 311 map_addr = ELF_PAGESTART(addr);
315 * The _first_ mmap needs to know the full size, otherwise
316 * randomization might put this image into an overlapping
317 * position with the ELF binary image. (since size < total_size)
318 * So we first map the 'big' image - and unmap the remainder at
319 * the end. (which unmap is needed for ELF images with holes.)
320 */
321 if (total_size) {
322 total_size = ELF_PAGEALIGN(total_size);
323 map_addr = do_mmap(filep, addr, total_size, prot, type, off);
324 if (!BAD_ADDR(map_addr))
325 do_munmap(current->mm, map_addr+size, total_size-size);
326 } else
327 map_addr = do_mmap(filep, addr, size, prot, type, off);
328
329 up_write(&current->mm->mmap_sem); 312 up_write(&current->mm->mmap_sem);
330 return(map_addr); 313 return(map_addr);
331} 314}
332 315
333#endif /* !elf_map */ 316#endif /* !elf_map */
334 317
335static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
336{
337 int i, first_idx = -1, last_idx = -1;
338
339 for (i = 0; i < nr; i++) {
340 if (cmds[i].p_type == PT_LOAD) {
341 last_idx = i;
342 if (first_idx == -1)
343 first_idx = i;
344 }
345 }
346 if (first_idx == -1)
347 return 0;
348
349 return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
350 ELF_PAGESTART(cmds[first_idx].p_vaddr);
351}
352
353
354/* This is much more generalized than the library routine read function, 318/* This is much more generalized than the library routine read function,
355 so we keep this separate. Technically the library read function 319 so we keep this separate. Technically the library read function
356 is only provided so that we can read a.out libraries that have 320 is only provided so that we can read a.out libraries that have
357 an ELF header */ 321 an ELF header */
358 322
359static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, 323static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
360 struct file *interpreter, unsigned long *interp_map_addr, 324 struct file *interpreter, unsigned long *interp_load_addr)
361 unsigned long no_base)
362{ 325{
363 struct elf_phdr *elf_phdata; 326 struct elf_phdr *elf_phdata;
364 struct elf_phdr *eppnt; 327 struct elf_phdr *eppnt;
@@ -366,7 +329,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
366 int load_addr_set = 0; 329 int load_addr_set = 0;
367 unsigned long last_bss = 0, elf_bss = 0; 330 unsigned long last_bss = 0, elf_bss = 0;
368 unsigned long error = ~0UL; 331 unsigned long error = ~0UL;
369 unsigned long total_size;
370 int retval, i, size; 332 int retval, i, size;
371 333
372 /* First of all, some simple consistency checks */ 334 /* First of all, some simple consistency checks */
@@ -405,12 +367,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
405 goto out_close; 367 goto out_close;
406 } 368 }
407 369
408 total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
409 if (!total_size) {
410 error = -EINVAL;
411 goto out_close;
412 }
413
414 eppnt = elf_phdata; 370 eppnt = elf_phdata;
415 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { 371 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
416 if (eppnt->p_type == PT_LOAD) { 372 if (eppnt->p_type == PT_LOAD) {
@@ -428,14 +384,9 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
428 vaddr = eppnt->p_vaddr; 384 vaddr = eppnt->p_vaddr;
429 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) 385 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
430 elf_type |= MAP_FIXED; 386 elf_type |= MAP_FIXED;
431 else if (no_base && interp_elf_ex->e_type == ET_DYN)
432 load_addr = -vaddr;
433 387
434 map_addr = elf_map(interpreter, load_addr + vaddr, 388 map_addr = elf_map(interpreter, load_addr + vaddr,
435 eppnt, elf_prot, elf_type, total_size); 389 eppnt, elf_prot, elf_type);
436 total_size = 0;
437 if (!*interp_map_addr)
438 *interp_map_addr = map_addr;
439 error = map_addr; 390 error = map_addr;
440 if (BAD_ADDR(map_addr)) 391 if (BAD_ADDR(map_addr))
441 goto out_close; 392 goto out_close;
@@ -501,7 +452,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
501 goto out_close; 452 goto out_close;
502 } 453 }
503 454
504 error = load_addr; 455 *interp_load_addr = load_addr;
456 error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
505 457
506out_close: 458out_close:
507 kfree(elf_phdata); 459 kfree(elf_phdata);
@@ -598,8 +550,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
598 int elf_exec_fileno; 550 int elf_exec_fileno;
599 int retval, i; 551 int retval, i;
600 unsigned int size; 552 unsigned int size;
601 unsigned long elf_entry; 553 unsigned long elf_entry, interp_load_addr = 0;
602 unsigned long interp_load_addr = 0;
603 unsigned long start_code, end_code, start_data, end_data; 554 unsigned long start_code, end_code, start_data, end_data;
604 unsigned long reloc_func_desc = 0; 555 unsigned long reloc_func_desc = 0;
605 char passed_fileno[6]; 556 char passed_fileno[6];
@@ -863,7 +814,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
863 current->mm->start_stack = bprm->p; 814 current->mm->start_stack = bprm->p;
864 815
865 /* Now we do a little grungy work by mmaping the ELF image into 816 /* Now we do a little grungy work by mmaping the ELF image into
866 the correct location in memory. */ 817 the correct location in memory. At this point, we assume that
818 the image should be loaded at fixed address, not at a variable
819 address. */
867 for(i = 0, elf_ppnt = elf_phdata; 820 for(i = 0, elf_ppnt = elf_phdata;
868 i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { 821 i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
869 int elf_prot = 0, elf_flags; 822 int elf_prot = 0, elf_flags;
@@ -917,15 +870,11 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
917 * default mmap base, as well as whatever program they 870 * default mmap base, as well as whatever program they
918 * might try to exec. This is because the brk will 871 * might try to exec. This is because the brk will
919 * follow the loader, and is not movable. */ 872 * follow the loader, and is not movable. */
920#ifdef CONFIG_X86
921 load_bias = 0;
922#else
923 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); 873 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
924#endif
925 } 874 }
926 875
927 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, 876 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
928 elf_prot, elf_flags,0); 877 elf_prot, elf_flags);
929 if (BAD_ADDR(error)) { 878 if (BAD_ADDR(error)) {
930 send_sig(SIGKILL, current, 0); 879 send_sig(SIGKILL, current, 0);
931 retval = IS_ERR((void *)error) ? 880 retval = IS_ERR((void *)error) ?
@@ -1001,25 +950,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1001 } 950 }
1002 951
1003 if (elf_interpreter) { 952 if (elf_interpreter) {
1004 if (interpreter_type == INTERPRETER_AOUT) { 953 if (interpreter_type == INTERPRETER_AOUT)
1005 elf_entry = load_aout_interp(&loc->interp_ex, 954 elf_entry = load_aout_interp(&loc->interp_ex,
1006 interpreter); 955 interpreter);
1007 } else { 956 else
1008 unsigned long uninitialized_var(interp_map_addr);
1009
1010 elf_entry = load_elf_interp(&loc->interp_elf_ex, 957 elf_entry = load_elf_interp(&loc->interp_elf_ex,
1011 interpreter, 958 interpreter,
1012 &interp_map_addr, 959 &interp_load_addr);
1013 load_bias);
1014 if (!BAD_ADDR(elf_entry)) {
1015 /*
1016 * load_elf_interp() returns relocation
1017 * adjustment
1018 */
1019 interp_load_addr = elf_entry;
1020 elf_entry += loc->interp_elf_ex.e_entry;
1021 }
1022 }
1023 if (BAD_ADDR(elf_entry)) { 960 if (BAD_ADDR(elf_entry)) {
1024 force_sig(SIGSEGV, current); 961 force_sig(SIGSEGV, current);
1025 retval = IS_ERR((void *)elf_entry) ? 962 retval = IS_ERR((void *)elf_entry) ?