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