Commit d4e3cc38 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 80e27982
...@@ -226,7 +226,7 @@ elf32_set_personality (void) ...@@ -226,7 +226,7 @@ elf32_set_personality (void)
} }
static unsigned long static unsigned long
elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused) elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
{ {
unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK; unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_elf_library(struct file *); static int load_elf_library(struct file *);
static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long); static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
/* /*
* If we don't support core dumping, then supply a NULL so we * If we don't support core dumping, then supply a NULL so we
...@@ -80,7 +80,7 @@ static struct linux_binfmt elf_format = { ...@@ -80,7 +80,7 @@ static struct linux_binfmt elf_format = {
.hasvdso = 1 .hasvdso = 1
}; };
#define BAD_ADDR(x) IS_ERR_VALUE(x) #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
static int set_brk(unsigned long start, unsigned long end) static int set_brk(unsigned long start, unsigned long end)
{ {
...@@ -295,70 +295,33 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, ...@@ -295,70 +295,33 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
#ifndef elf_map #ifndef elf_map
static unsigned long elf_map(struct file *filep, unsigned long addr, static unsigned long elf_map(struct file *filep, unsigned long addr,
struct elf_phdr *eppnt, int prot, int type, struct elf_phdr *eppnt, int prot, int type)
unsigned long total_size)
{ {
unsigned long map_addr; unsigned long map_addr;
unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
addr = ELF_PAGESTART(addr);
size = ELF_PAGEALIGN(size);
down_write(&current->mm->mmap_sem);
/* mmap() will return -EINVAL if given a zero size, but a /* mmap() will return -EINVAL if given a zero size, but a
* segment with zero filesize is perfectly valid */ * segment with zero filesize is perfectly valid */
if (!size) if (eppnt->p_filesz + pageoffset)
return addr; map_addr = do_mmap(filep, ELF_PAGESTART(addr),
eppnt->p_filesz + pageoffset, prot, type,
down_write(&current->mm->mmap_sem); eppnt->p_offset - pageoffset);
/* else
* total_size is the size of the ELF (interpreter) image. map_addr = ELF_PAGESTART(addr);
* The _first_ mmap needs to know the full size, otherwise
* randomization might put this image into an overlapping
* position with the ELF binary image. (since size < total_size)
* So we first map the 'big' image - and unmap the remainder at
* the end. (which unmap is needed for ELF images with holes.)
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
map_addr = do_mmap(filep, addr, total_size, prot, type, off);
if (!BAD_ADDR(map_addr))
do_munmap(current->mm, map_addr+size, total_size-size);
} else
map_addr = do_mmap(filep, addr, size, prot, type, off);
up_write(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
return(map_addr); return(map_addr);
} }
#endif /* !elf_map */ #endif /* !elf_map */
static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
{
int i, first_idx = -1, last_idx = -1;
for (i = 0; i < nr; i++) {
if (cmds[i].p_type == PT_LOAD) {
last_idx = i;
if (first_idx == -1)
first_idx = i;
}
}
if (first_idx == -1)
return 0;
return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
ELF_PAGESTART(cmds[first_idx].p_vaddr);
}
/* This is much more generalized than the library routine read function, /* This is much more generalized than the library routine read function,
so we keep this separate. Technically the library read function so we keep this separate. Technically the library read function
is only provided so that we can read a.out libraries that have is only provided so that we can read a.out libraries that have
an ELF header */ an ELF header */
static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
struct file *interpreter, unsigned long *interp_map_addr, struct file *interpreter, unsigned long *interp_load_addr)
unsigned long no_base)
{ {
struct elf_phdr *elf_phdata; struct elf_phdr *elf_phdata;
struct elf_phdr *eppnt; struct elf_phdr *eppnt;
...@@ -366,7 +329,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, ...@@ -366,7 +329,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
int load_addr_set = 0; int load_addr_set = 0;
unsigned long last_bss = 0, elf_bss = 0; unsigned long last_bss = 0, elf_bss = 0;
unsigned long error = ~0UL; unsigned long error = ~0UL;
unsigned long total_size;
int retval, i, size; int retval, i, size;
/* First of all, some simple consistency checks */ /* First of all, some simple consistency checks */
...@@ -405,12 +367,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, ...@@ -405,12 +367,6 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
goto out_close; goto out_close;
} }
total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
if (!total_size) {
error = -EINVAL;
goto out_close;
}
eppnt = elf_phdata; eppnt = elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) { if (eppnt->p_type == PT_LOAD) {
...@@ -428,14 +384,9 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, ...@@ -428,14 +384,9 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
vaddr = eppnt->p_vaddr; vaddr = eppnt->p_vaddr;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
elf_type |= MAP_FIXED; elf_type |= MAP_FIXED;
else if (no_base && interp_elf_ex->e_type == ET_DYN)
load_addr = -vaddr;
map_addr = elf_map(interpreter, load_addr + vaddr, map_addr = elf_map(interpreter, load_addr + vaddr,
eppnt, elf_prot, elf_type, total_size); eppnt, elf_prot, elf_type);
total_size = 0;
if (!*interp_map_addr)
*interp_map_addr = map_addr;
error = map_addr; error = map_addr;
if (BAD_ADDR(map_addr)) if (BAD_ADDR(map_addr))
goto out_close; goto out_close;
...@@ -501,7 +452,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, ...@@ -501,7 +452,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
goto out_close; goto out_close;
} }
error = load_addr; *interp_load_addr = load_addr;
error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
out_close: out_close:
kfree(elf_phdata); kfree(elf_phdata);
...@@ -598,8 +550,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -598,8 +550,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
int elf_exec_fileno; int elf_exec_fileno;
int retval, i; int retval, i;
unsigned int size; unsigned int size;
unsigned long elf_entry; unsigned long elf_entry, interp_load_addr = 0;
unsigned long interp_load_addr = 0;
unsigned long start_code, end_code, start_data, end_data; unsigned long start_code, end_code, start_data, end_data;
unsigned long reloc_func_desc = 0; unsigned long reloc_func_desc = 0;
char passed_fileno[6]; char passed_fileno[6];
...@@ -863,7 +814,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -863,7 +814,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->start_stack = bprm->p; current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into /* Now we do a little grungy work by mmaping the ELF image into
the correct location in memory. */ the correct location in memory. At this point, we assume that
the image should be loaded at fixed address, not at a variable
address. */
for(i = 0, elf_ppnt = elf_phdata; for(i = 0, elf_ppnt = elf_phdata;
i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0, elf_flags; int elf_prot = 0, elf_flags;
...@@ -917,15 +870,11 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -917,15 +870,11 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
* default mmap base, as well as whatever program they * default mmap base, as well as whatever program they
* might try to exec. This is because the brk will * might try to exec. This is because the brk will
* follow the loader, and is not movable. */ * follow the loader, and is not movable. */
#ifdef CONFIG_X86
load_bias = 0;
#else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
#endif
} }
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
elf_prot, elf_flags,0); elf_prot, elf_flags);
if (BAD_ADDR(error)) { if (BAD_ADDR(error)) {
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
retval = IS_ERR((void *)error) ? retval = IS_ERR((void *)error) ?
...@@ -1001,25 +950,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -1001,25 +950,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
} }
if (elf_interpreter) { if (elf_interpreter) {
if (interpreter_type == INTERPRETER_AOUT) { if (interpreter_type == INTERPRETER_AOUT)
elf_entry = load_aout_interp(&loc->interp_ex, elf_entry = load_aout_interp(&loc->interp_ex,
interpreter); interpreter);
} else { else
unsigned long uninitialized_var(interp_map_addr);
elf_entry = load_elf_interp(&loc->interp_elf_ex, elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter, interpreter,
&interp_map_addr, &interp_load_addr);
load_bias);
if (!BAD_ADDR(elf_entry)) {
/*
* load_elf_interp() returns relocation
* adjustment
*/
interp_load_addr = elf_entry;
elf_entry += loc->interp_elf_ex.e_entry;
}
}
if (BAD_ADDR(elf_entry)) { if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
retval = IS_ERR((void *)elf_entry) ? retval = IS_ERR((void *)elf_entry) ?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment