[PATCH] ppc64: Improve mapping of vDSO

Benjamin Herrenschmidt benh at kernel.crashing.org
Wed Apr 6 14:10:38 EST 2005


Hi Andrew !

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.

Please apply for 2.6.12,

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>


Index: linux-work/arch/ppc64/kernel/vdso.c
===================================================================
--- linux-work.orig/arch/ppc64/kernel/vdso.c	2005-03-07 10:22:15.000000000 +1100
+++ linux-work/arch/ppc64/kernel/vdso.c	2005-04-06 13:32:41.000000000 +1000
@@ -213,13 +213,14 @@
 		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 @@
 	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;
Index: linux-work/fs/binfmt_elf.c
===================================================================
--- linux-work.orig/fs/binfmt_elf.c	2005-04-03 10:02:57.000000000 +1000
+++ linux-work/fs/binfmt_elf.c	2005-04-06 13:10:49.000000000 +1000
@@ -782,14 +782,6 @@
 		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 @@
 
 	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),
Index: linux-work/include/asm-ppc64/vdso.h
===================================================================
--- linux-work.orig/include/asm-ppc64/vdso.h	2005-03-15 11:57:38.000000000 +1100
+++ linux-work/include/asm-ppc64/vdso.h	2005-04-06 13:33:20.000000000 +1000
@@ -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
 





More information about the Linuxppc64-dev mailing list