aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-04-16 18:24:35 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:24:35 -0400
commit547ee84cea37696d25c93306e909378a87db2f66 (patch)
treee21a5ce886975623d07add60beb223e6f36bab80
parentfa89c5092eddcbcb425a1416f85906e3cc519793 (diff)
[PATCH] ppc64: Improve mapping of vDSO
This patch reworks the way the ppc64 is mapped in user memory by the kernel to make it more robust against possible collisions with executable segments. Instead of just whacking a VMA at 1Mb, I now use get_unmapped_area() with a hint, and I moved the mapping of the vDSO to after the mapping of the various ELF segments and of the interpreter, so that conflicts get caught properly (it still has to be before create_elf_tables since the later will fill the AT_SYSINFO_EHDR with the proper address). While I was at it, I also changed the 32 and 64 bits vDSO's to link at their "natural" address of 1Mb instead of 0. This is the address where they are normally mapped in absence of conflict. By doing so, it should be possible to properly prelink one it's been verified to work on glibc. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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)
213 vdso_base = VDSO64_MBASE; 213 vdso_base = VDSO64_MBASE;
214 } 214 }
215 215
216 current->thread.vdso_base = 0;
217
216 /* vDSO has a problem and was disabled, just don't "enable" it for the 218 /* vDSO has a problem and was disabled, just don't "enable" it for the
217 * process 219 * process
218 */ 220 */
219 if (vdso_pages == 0) { 221 if (vdso_pages == 0)
220 current->thread.vdso_base = 0;
221 return 0; 222 return 0;
222 } 223
223 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); 224 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
224 if (vma == NULL) 225 if (vma == NULL)
225 return -ENOMEM; 226 return -ENOMEM;
@@ -230,12 +231,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
230 memset(vma, 0, sizeof(*vma)); 231 memset(vma, 0, sizeof(*vma));
231 232
232 /* 233 /*
233 * pick a base address for the vDSO in process space. We have a default 234 * pick a base address for the vDSO in process space. We try to put it
234 * base of 1Mb on which we had a random offset up to 1Mb. 235 * at vdso_base which is the "natural" base for it, but we might fail
235 * XXX: Add possibility for a program header to specify that location 236 * and end up putting it elsewhere.
236 */ 237 */
238 vdso_base = get_unmapped_area(NULL, vdso_base,
239 vdso_pages << PAGE_SHIFT, 0, 0);
240 if (vdso_base & ~PAGE_MASK)
241 return (int)vdso_base;
242
237 current->thread.vdso_base = vdso_base; 243 current->thread.vdso_base = vdso_base;
238 /* + ((unsigned long)vma & 0x000ff000); */
239 244
240 vma->vm_mm = mm; 245 vma->vm_mm = mm;
241 vma->vm_start = current->thread.vdso_base; 246 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)
782 goto out_free_dentry; 782 goto out_free_dentry;
783 } 783 }
784 784
785#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
786 retval = arch_setup_additional_pages(bprm, executable_stack);
787 if (retval < 0) {
788 send_sig(SIGKILL, current, 0);
789 goto out_free_dentry;
790 }
791#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
792
793 current->mm->start_stack = bprm->p; 785 current->mm->start_stack = bprm->p;
794 786
795 /* Now we do a little grungy work by mmaping the ELF image into 787 /* 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)
949 941
950 set_binfmt(&elf_format); 942 set_binfmt(&elf_format);
951 943
944#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
945 retval = arch_setup_additional_pages(bprm, executable_stack);
946 if (retval < 0) {
947 send_sig(SIGKILL, current, 0);
948 goto out_free_dentry;
949 }
950#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
951
952 compute_creds(bprm); 952 compute_creds(bprm);
953 current->flags &= ~PF_FORKNOEXEC; 953 current->flags &= ~PF_FORKNOEXEC;
954 create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT), 954 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 @@
4#ifdef __KERNEL__ 4#ifdef __KERNEL__
5 5
6/* Default link addresses for the vDSOs */ 6/* Default link addresses for the vDSOs */
7#define VDSO32_LBASE 0 7#define VDSO32_LBASE 0x100000
8#define VDSO64_LBASE 0 8#define VDSO64_LBASE 0x100000
9 9
10/* Default map addresses */ 10/* Default map addresses */
11#define VDSO32_MBASE 0x100000 11#define VDSO32_MBASE VDSO32_LBASE
12#define VDSO64_MBASE 0x100000 12#define VDSO64_MBASE VDSO64_LBASE
13 13
14#define VDSO_VERSION_STRING LINUX_2.6.12 14#define VDSO_VERSION_STRING LINUX_2.6.12
15 15