summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/vdso.c19
-rw-r--r--fs/binfmt_elf.c16
-rw-r--r--include/asm-ppc64/vdso.h8
3 files changed, 24 insertions, 19 deletions
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
index 8c4597224b71..4777676365fe 100644
--- a/arch/ppc64/kernel/vdso.c
+++ b/arch/ppc64/kernel/vdso.c
@@ -213,13 +213,14 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
vdso_base = VDSO64_MBASE;
}
+ current->thread.vdso_base = 0;
+
/* vDSO has a problem and was disabled, just don't "enable" it for the
* process
*/
- if (vdso_pages == 0) {
- current->thread.vdso_base = 0;
+ if (vdso_pages == 0)
return 0;
- }
+
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma == NULL)
return -ENOMEM;
@@ -230,12 +231,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
memset(vma, 0, sizeof(*vma));
/*
- * pick a base address for the vDSO in process space. We have a default
- * base of 1Mb on which we had a random offset up to 1Mb.
- * XXX: Add possibility for a program header to specify that location
+ * pick a base address for the vDSO in process space. We try to put it
+ * at vdso_base which is the "natural" base for it, but we might fail
+ * and end up putting it elsewhere.
*/
+ vdso_base = get_unmapped_area(NULL, vdso_base,
+ vdso_pages << PAGE_SHIFT, 0, 0);
+ if (vdso_base & ~PAGE_MASK)
+ return (int)vdso_base;
+
current->thread.vdso_base = vdso_base;
- /* + ((unsigned long)vma & 0x000ff000); */
vma->vm_mm = mm;
vma->vm_start = current->thread.vdso_base;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 76ec9d8939ff..6ae62cbf7c2e 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -782,14 +782,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out_free_dentry;
}
-#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
- retval = arch_setup_additional_pages(bprm, executable_stack);
- if (retval < 0) {
- send_sig(SIGKILL, current, 0);
- goto out_free_dentry;
- }
-#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
-
current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
@@ -949,6 +941,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
set_binfmt(&elf_format);
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ retval = arch_setup_additional_pages(bprm, executable_stack);
+ if (retval < 0) {
+ send_sig(SIGKILL, current, 0);
+ goto out_free_dentry;
+ }
+#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
diff --git a/include/asm-ppc64/vdso.h b/include/asm-ppc64/vdso.h
index b74e16c0cf01..85d8a7be25c4 100644
--- a/include/asm-ppc64/vdso.h
+++ b/include/asm-ppc64/vdso.h
@@ -4,12 +4,12 @@
#ifdef __KERNEL__
/* Default link addresses for the vDSOs */
-#define VDSO32_LBASE 0
-#define VDSO64_LBASE 0
+#define VDSO32_LBASE 0x100000
+#define VDSO64_LBASE 0x100000
/* Default map addresses */
-#define VDSO32_MBASE 0x100000
-#define VDSO64_MBASE 0x100000
+#define VDSO32_MBASE VDSO32_LBASE
+#define VDSO64_MBASE VDSO64_LBASE
#define VDSO_VERSION_STRING LINUX_2.6.12