Re: [patch] i386, vdso=[0|1] boot option and /proc/sys/vm/vdso_enabled

Ingo Molnar
2006-05-21T11:03:02Z

* Andrew Morton <akpm@osdl.org> wrote:

> > Andrew, could you try this - do newly started processes work fine if you
> > re-enable the vdso after booting with vdso=0?
>
> vmm:/home/akpm# echo 1 > /proc/sys/vm/vdso_enabled
> vmm:/home/akpm#
> vmm:/home/akpm> ls -l
> zsh: segmentation fault ls -l

Andrew, could you try the patch below, does your FC1 box work with it
applied and CONFIG_COMPAT_VDSO enabled? (no need to pass any boot
options)

The config option reinstates the high mapping, so that old glibc can
reference it as data (that is i think what happened in the original FC1
glibc). Newer distributions can (and will) turn this off. The option
defaults to y, so that we are compatible by default.

( Small additional detail: to further limit the security impact of the
workaround, the page is nonexec, so on the unlikely chance of someone
running a FC1 glibc with a new kernel on new, NX-capable hardware
using the PAE i386 kernel, execution is denied on that page. [i have
tested this kernel combination and execution is indeed denied in that
case.] )

Ingo

---
Subject: vDSO: provide workaround for older glibcs
From: Ingo Molnar <mingo@elte.hu>

this patch adds CONFIG_COMPAT_VDSO (default=y), which provides support
for older glibcs to reference the high-mapped VDSO. Newer distributions
(anything newer than say 2 years) can turn this off.

NOTE: the exec bit is turned off for the vDSO, because glibc only
reference the vDSO, but dont try to execute it.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/i386/Kconfig | 9 +++++++++
arch/i386/kernel/sysenter.c | 5 +++++
2 files changed, 14 insertions(+)

Index: linux-vdso-rand.q/arch/i386/Kconfig
===================================================================
--- linux-vdso-rand.q.orig/arch/i386/Kconfig
+++ linux-vdso-rand.q/arch/i386/Kconfig
@@ -762,6 +762,15 @@ config HOTPLUG_CPU
enable suspend on SMP systems. CPUs can be controlled through
/sys/devices/system/cpu.

+config COMPAT_VDSO
+ bool "Compat VDSO support"
+ default y
+ help
+ Map the VDSO to the fixed old-style address too.
+ ---help---
+ Say N here if you are running a sufficiently recent glibc
+ version, to remove the (unused) high-mapped VDSO mapping.
+ If unsure, say Y.

endmenu

Index: linux-vdso-rand.q/arch/i386/kernel/sysenter.c
===================================================================
--- linux-vdso-rand.q.orig/arch/i386/kernel/sysenter.c
+++ linux-vdso-rand.q/arch/i386/kernel/sysenter.c
@@ -69,6 +69,11 @@ int __init sysenter_setup(void)
{
syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);

+#ifdef CONFIG_COMPAT_VDSO
+ __set_fixmap(FIX_VSYSCALL, __pa(syscall_page), PAGE_READONLY);
+ printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VSYSCALL));
+#endif
+
if (!boot_cpu_has(X86_FEATURE_SEP)) {
memcpy(syscall_page,
&vsyscall_int80_start,