Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0b49f26 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by H. Peter Anvin
Browse files

x86, vdso: Remove compat vdso support



The compat vDSO is a complicated hack that's needed to maintain
compatibility with a small range of glibc versions.

This removes it and replaces it with a much simpler hack: a config
option to disable the 32-bit vDSO by default.

This also changes the default value of CONFIG_COMPAT_VDSO to n --
users configuring kernels from scratch almost certainly want that
choice.

Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/4bb4690899106eb11430b1186d5cc66ca9d1660c.1394751608.git.luto@amacapital.net


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent fa389e22
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -3409,14 +3409,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
					of CONFIG_HIGHPTE.

	vdso=		[X86,SH]
			vdso=2: enable compat VDSO (default with COMPAT_VDSO)
			vdso=1: enable VDSO (default)
			On X86_32, this is an alias for vdso32=.  Otherwise:

			vdso=1: enable VDSO (the default)
			vdso=0: disable VDSO mapping

	vdso32=		[X86]
			vdso32=2: enable compat VDSO (default with COMPAT_VDSO)
			vdso32=1: enable 32-bit VDSO (default)
			vdso32=0: disable 32-bit VDSO mapping
	vdso32=		[X86] Control the 32-bit vDSO
			vdso32=1: enable 32-bit VDSO
			vdso32=0 or vdso32=2: disable 32-bit VDSO

			See the help text for CONFIG_COMPAT_VDSO for more
			details.  If CONFIG_COMPAT_VDSO is set, the default is
			vdso32=0; otherwise, the default is vdso32=1.

			For compatibility with older kernels, vdso32=2 is an
			alias for vdso32=0.

			Try vdso32=0 if you encounter an error that says:
			dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!

	vector=		[IA-64,SMP]
			vector=percpu: enable percpu vector domain
+19 −7
Original line number Diff line number Diff line
@@ -1836,17 +1836,29 @@ config DEBUG_HOTPLUG_CPU0
	  If unsure, say N.

config COMPAT_VDSO
	def_bool y
	prompt "Compat VDSO support"
	def_bool n
	prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)"
	depends on X86_32 || IA32_EMULATION
	---help---
	  Map the 32-bit VDSO to the predictable old-style address too.
	  Certain buggy versions of glibc will crash if they are
	  presented with a 32-bit vDSO that is not mapped at the address
	  indicated in its segment table.

	  Say N here if you are running a sufficiently recent glibc
	  version (2.3.3 or later), to remove the high-mapped
	  VDSO mapping and to exclusively use the randomized VDSO.
	  The bug was introduced by f866314b89d56845f55e6f365e18b31ec978ec3a
	  and fixed by 3b3ddb4f7db98ec9e912ccdf54d35df4aa30e04a and
	  49ad572a70b8aeb91e57483a11dd1b77e31c4468.  Glibc 2.3.3 is
	  the only released version with the bug, but OpenSUSE 9
	  contains a buggy "glibc 2.3.2".

	  If unsure, say Y.
	  The symptom of the bug is that everything crashes on startup, saying:
	  dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!

	  Saying Y here changes the default value of the vdso32 boot
	  option from 1 to 0, which turns off the 32-bit vDSO entirely.
	  This works around the glibc bug but hurts performance.

	  If unsure, say N: if you are compiling your own kernel, you
	  are unlikely to be using a buggy version of glibc.

config CMDLINE_BOOL
	bool "Built-in kernel command line"
+0 −4
Original line number Diff line number Diff line
@@ -281,16 +281,12 @@ do { \

#define STACK_RND_MASK (0x7ff)

#define VDSO_HIGH_BASE		(__fix_to_virt(FIX_VDSO))

#define ARCH_DLINFO		ARCH_DLINFO_IA32(vdso_enabled)

/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */

#else /* CONFIG_X86_32 */

#define VDSO_HIGH_BASE		0xffffe000U /* CONFIG_COMPAT_VDSO address */

/* 1GB for 64bit, 8MB for 32bit */
#define STACK_RND_MASK (test_thread_flag(TIF_ADDR32) ? 0x7ff : 0x3fffff)

+0 −8
Original line number Diff line number Diff line
@@ -40,15 +40,8 @@
 */
extern unsigned long __FIXADDR_TOP;
#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)

#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
#else
#define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)

/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
#define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
#endif


@@ -74,7 +67,6 @@ extern unsigned long __FIXADDR_TOP;
enum fixed_addresses {
#ifdef CONFIG_X86_32
	FIX_HOLE,
	FIX_VDSO,
#else
	VSYSCALL_LAST_PAGE,
	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+1 −4
Original line number Diff line number Diff line
@@ -2,8 +2,6 @@
#define _ASM_X86_VDSO_H

#if defined CONFIG_X86_32 || defined CONFIG_COMPAT
extern const char VDSO32_PRELINK[];

/*
 * Given a pointer to the vDSO image, find the pointer to VDSO32_name
 * as that symbol is defined in the vDSO sources or linker script.
@@ -11,8 +9,7 @@ extern const char VDSO32_PRELINK[];
#define VDSO32_SYMBOL(base, name)					\
({									\
	extern const char VDSO32_##name[];				\
	(void __user *)(VDSO32_##name - VDSO32_PRELINK +		\
			(unsigned long)(base));				\
	(void __user *)(VDSO32_##name + (unsigned long)(base));		\
})
#endif

Loading