lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1440861626-27008-5-git-send-email-brgerst@gmail.com>
Date:	Sat, 29 Aug 2015 11:20:23 -0400
From:	Brian Gerst <brgerst@...il.com>
To:	x86@...nel.org, linux-kernel@...r.kernel.org
Cc:	Ingo Molnar <mingo@...nel.org>, "H. Peter Anvin" <hpa@...or.com>,
	Denys Vlasenko <dvlasenk@...hat.com>,
	Andy Lutomirski <luto@...capital.net>,
	Linus Torvalds <torvalds@...ux-foundation.org>
Subject: [PATCH 4/7] x86/vdso32: Build single vdso32 image

Currently, there are three images that are built for vdso32, differing
only in the syscall entry code.  The syscall entry is a tiny fraction of
the total code, so most of the vdso code is duplicated in memory three
times.  This patch merges all the syscall entry points into one image,
and instead of selecting the image, selects the entry point that is placed
in the AT_SYSINFO vector and the ELF entry point.

Signed-off-by: Brian Gerst <brgerst@...il.com>
---
 arch/x86/entry/vdso/.gitignore        |  3 ---
 arch/x86/entry/vdso/Makefile          | 44 ++++++++++++-----------------------
 arch/x86/entry/vdso/vdso2c.c          |  2 ++
 arch/x86/entry/vdso/vdso32-setup.c    | 15 ++++++------
 arch/x86/entry/vdso/vdso32/syscall.S  |  8 +++----
 arch/x86/entry/vdso/vdso32/sysenter.S |  8 +++----
 arch/x86/entry/vdso/vma.c             |  6 ++---
 arch/x86/ia32/ia32_signal.c           |  4 ++--
 arch/x86/include/asm/elf.h            |  3 +--
 arch/x86/include/asm/vdso.h           | 11 ++++-----
 arch/x86/kernel/signal.c              |  4 ++--
 arch/x86/xen/setup.c                  | 12 ++--------
 12 files changed, 47 insertions(+), 73 deletions(-)

diff --git a/arch/x86/entry/vdso/.gitignore b/arch/x86/entry/vdso/.gitignore
index aae8ffd..a6a6ca8 100644
--- a/arch/x86/entry/vdso/.gitignore
+++ b/arch/x86/entry/vdso/.gitignore
@@ -1,7 +1,4 @@
 vdso.lds
 vdsox32.lds
-vdso32-syscall-syms.lds
-vdso32-sysenter-syms.lds
-vdso32-int80-syms.lds
 vdso-image-*.c
 vdso2c
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index b4cd431..282121a 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -19,9 +19,7 @@ obj-y				+= vma.o
 # vDSO images to build
 vdso_img-$(VDSO64-y)		+= 64
 vdso_img-$(VDSOX32-y)		+= x32
-vdso_img-$(VDSO32-y)		+= 32-int80
-vdso_img-$(CONFIG_IA32_EMULATION)	+= 32-syscall
-vdso_img-$(VDSO32-y)		+= 32-sysenter
+vdso_img-$(VDSO32-y)		+= 32
 
 obj-$(VDSO32-y)			+= vdso32-setup.o
 
@@ -122,15 +120,6 @@ $(obj)/%.so: $(obj)/%.so.dbg
 $(obj)/vdsox32.so.dbg: $(src)/vdsox32.lds $(vobjx32s) FORCE
 	$(call if_changed,vdso)
 
-#
-# Build multiple 32-bit vDSO images to choose from at boot time.
-#
-vdso32.so-$(VDSO32-y)		+= int80
-vdso32.so-$(CONFIG_IA32_EMULATION)	+= syscall
-vdso32.so-$(VDSO32-y)		+= sysenter
-
-vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
-
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
 VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
 
@@ -138,15 +127,9 @@ VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
 # is not a kbuild sub-make subdirectory.
 override obj-dirs = $(dir $(obj)) $(obj)/vdso32/
 
-targets += vdso32/vdso32.lds
-targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o)
-targets += vdso32/vclock_gettime.o vdso32/sigreturn.o
-
-$(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%)
-
 KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
-$(vdso32-images:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
-$(vdso32-images:%=$(obj)/%.dbg): asflags-$(CONFIG_X86_64) += -m32
+$(obj)/vdso32.so.dbg: KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
+$(obj)/vdso32.so.dbg: asflags-$(CONFIG_X86_64) += -m32
 
 KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32))
@@ -157,14 +140,17 @@ KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
 KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
 KBUILD_CFLAGS_32 += -fno-omit-frame-pointer
 KBUILD_CFLAGS_32 += -DDISABLE_BRANCH_PROFILING
-$(vdso32-images:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
-
-$(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
-				 $(obj)/vdso32/vdso32.lds \
-				 $(obj)/vdso32/vclock_gettime.o \
-				 $(obj)/vdso32/note.o \
-				 $(obj)/vdso32/sigreturn.o \
-				 $(obj)/vdso32/%.o
+
+vobjs32-y := vdso32/vclock_gettime.o vdso32/note.o vdso32/sigreturn.o
+vobjs32-y += vdso32/int80.o vdso32/sysenter.o
+vobjs32-$(CONFIG_COMPAT) += vdso32/syscall.o
+
+vobjs32 := $(foreach F,$(vobjs32-y),$(obj)/$F)
+
+targets += vdso32/vdso32.lds $(vobjs32-y)
+
+$(obj)/vdso32.so.dbg: KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
+$(obj)/vdso32.so.dbg: $(obj)/vdso32/vdso32.lds $(vobjs32) FORCE
 	$(call if_changed,vdso)
 
 #
@@ -207,4 +193,4 @@ $(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
 PHONY += vdso_install $(vdso_img_insttargets)
 vdso_install: $(vdso_img_insttargets) FORCE
 
-clean-files := vdso32-syscall* vdso32-sysenter* vdso32-int80* vdso64* vdso-image-*.c vdsox32.so*
+clean-files := vdso32* vdso64* vdso-image-*.c vdsox32.so*
diff --git a/arch/x86/entry/vdso/vdso2c.c b/arch/x86/entry/vdso/vdso2c.c
index 8627db2..cda5fa8 100644
--- a/arch/x86/entry/vdso/vdso2c.c
+++ b/arch/x86/entry/vdso/vdso2c.c
@@ -100,6 +100,8 @@ struct vdso_sym required_syms[] = {
 	{"VDSO32_NOTE_MASK", true},
 	{"VDSO32_SYSENTER_RETURN", true},
 	{"__kernel_vsyscall", true},
+	{"__kernel_vsyscall_syscall", true},
+	{"__kernel_vsyscall_sysenter", true},
 	{"__kernel_sigreturn", true},
 	{"__kernel_rt_sigreturn", true},
 };
diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
index e904c27..d644762 100644
--- a/arch/x86/entry/vdso/vdso32-setup.c
+++ b/arch/x86/entry/vdso/vdso32-setup.c
@@ -10,6 +10,7 @@
 #include <linux/smp.h>
 #include <linux/kernel.h>
 #include <linux/mm_types.h>
+#include <linux/elf.h>
 
 #include <asm/cpufeature.h>
 #include <asm/processor.h>
@@ -60,23 +61,23 @@ __setup_param("vdso=", vdso_setup, vdso32_setup, 0);
 
 #endif	/* CONFIG_X86_64 */
 
-#if defined(CONFIG_X86_32) || defined(CONFIG_COMPAT)
-const struct vdso_image *selected_vdso32;
-#endif
+unsigned long selected_vsyscall;
 
 int __init sysenter_setup(void)
 {
 #ifdef CONFIG_COMPAT
 	if (vdso32_syscall())
-		selected_vdso32 = &vdso_image_32_syscall;
+		selected_vsyscall = vdso_image_32.sym___kernel_vsyscall_syscall;
 	else
 #endif
 	if (vdso32_sysenter())
-		selected_vdso32 = &vdso_image_32_sysenter;
+		selected_vsyscall = vdso_image_32.sym___kernel_vsyscall_sysenter;
 	else
-		selected_vdso32 = &vdso_image_32_int80;
+		selected_vsyscall = vdso_image_32.sym___kernel_vsyscall;
+
+	((struct elf32_hdr *)vdso_image_32.data)->e_entry = selected_vsyscall;
 
-	init_vdso_image(selected_vdso32);
+	init_vdso_image(&vdso_image_32);
 
 	return 0;
 }
diff --git a/arch/x86/entry/vdso/vdso32/syscall.S b/arch/x86/entry/vdso/vdso32/syscall.S
index 73f1428..50490c8 100644
--- a/arch/x86/entry/vdso/vdso32/syscall.S
+++ b/arch/x86/entry/vdso/vdso32/syscall.S
@@ -5,10 +5,10 @@
 #include <asm/segment.h>
 
 	.text
-	.globl __kernel_vsyscall
-	.type __kernel_vsyscall,@function
+	.globl __kernel_vsyscall_syscall
+	.type __kernel_vsyscall_syscall,@function
 	ALIGN
-__kernel_vsyscall:
+__kernel_vsyscall_syscall:
 .LSTART_vsyscall:
 	push	%ebp
 .Lpush_ebp:
@@ -19,7 +19,7 @@ __kernel_vsyscall:
 .Lpop_ebp:
 	ret
 .LEND_vsyscall:
-	.size __kernel_vsyscall,.-.LSTART_vsyscall
+	.size __kernel_vsyscall_syscall,.-.LSTART_vsyscall
 
 	.section .eh_frame,"a",@progbits
 .LSTARTFRAME:
diff --git a/arch/x86/entry/vdso/vdso32/sysenter.S b/arch/x86/entry/vdso/vdso32/sysenter.S
index e8e3080..458954a 100644
--- a/arch/x86/entry/vdso/vdso32/sysenter.S
+++ b/arch/x86/entry/vdso/vdso32/sysenter.S
@@ -22,10 +22,10 @@
  * three words on the parent stack do not get copied to the child.
  */
 	.text
-	.globl __kernel_vsyscall
-	.type __kernel_vsyscall,@function
+	.globl __kernel_vsyscall_sysenter
+	.type __kernel_vsyscall_sysenter,@function
 	ALIGN
-__kernel_vsyscall:
+__kernel_vsyscall_sysenter:
 .LSTART_vsyscall:
 	push %ecx
 .Lpush_ecx:
@@ -51,7 +51,7 @@ VDSO32_SYSENTER_RETURN:	/* Symbol used by sysenter.c via vdso32-syms.h */
 .Lpop_ecx:
 	ret
 .LEND_vsyscall:
-	.size __kernel_vsyscall,.-.LSTART_vsyscall
+	.size __kernel_vsyscall_sysenter,.-.LSTART_vsyscall
 	.previous
 
 	.section .eh_frame,"a",@progbits
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 4345431..c726d49 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -185,14 +185,14 @@ static int load_vdso32(void)
 	if (vdso32_enabled != 1)  /* Other values all mean "disabled" */
 		return 0;
 
-	ret = map_vdso(selected_vdso32, false);
+	ret = map_vdso(&vdso_image_32, false);
 	if (ret)
 		return ret;
 
-	if (selected_vdso32->sym_VDSO32_SYSENTER_RETURN)
+	if (vdso_image_32.sym_VDSO32_SYSENTER_RETURN)
 		current_thread_info()->sysenter_return =
 			current->mm->context.vdso +
-			selected_vdso32->sym_VDSO32_SYSENTER_RETURN;
+			vdso_image_32.sym_VDSO32_SYSENTER_RETURN;
 
 	return 0;
 }
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index a0a19b7..e6a5c275 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -289,7 +289,7 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
 		/* Return stub is in 32bit vsyscall page */
 		if (current->mm->context.vdso)
 			restorer = current->mm->context.vdso +
-				selected_vdso32->sym___kernel_sigreturn;
+				vdso_image_32.sym___kernel_sigreturn;
 		else
 			restorer = &frame->retcode;
 	}
@@ -368,7 +368,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
 			restorer = ksig->ka.sa.sa_restorer;
 		else
 			restorer = current->mm->context.vdso +
-				selected_vdso32->sym___kernel_rt_sigreturn;
+				vdso_image_32.sym___kernel_rt_sigreturn;
 		put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
 
 		/*
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 141c561..ccc1d31 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -327,8 +327,7 @@ else									\
 #define VDSO_CURRENT_BASE	((unsigned long)current->mm->context.vdso)
 
 #define VDSO_ENTRY							\
-	((unsigned long)current->mm->context.vdso +			\
-	 selected_vdso32->sym___kernel_vsyscall)
+	((unsigned long)current->mm->context.vdso + selected_vsyscall)
 
 struct linux_binprm;
 
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 8021bd2..16d5c18 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -26,6 +26,8 @@ struct vdso_image {
 	long sym___kernel_sigreturn;
 	long sym___kernel_rt_sigreturn;
 	long sym___kernel_vsyscall;
+	long sym___kernel_vsyscall_syscall;
+	long sym___kernel_vsyscall_sysenter;
 	long sym_VDSO32_SYSENTER_RETURN;
 };
 
@@ -38,13 +40,8 @@ extern const struct vdso_image vdso_image_x32;
 #endif
 
 #if defined CONFIG_X86_32 || defined CONFIG_COMPAT
-extern const struct vdso_image vdso_image_32_int80;
-#ifdef CONFIG_COMPAT
-extern const struct vdso_image vdso_image_32_syscall;
-#endif
-extern const struct vdso_image vdso_image_32_sysenter;
-
-extern const struct vdso_image *selected_vdso32;
+extern const struct vdso_image vdso_image_32;
+extern unsigned long selected_vsyscall;
 #endif
 
 extern void __init init_vdso_image(const struct vdso_image *image);
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index da52e6b..d87ce92 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -299,7 +299,7 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,
 
 	if (current->mm->context.vdso)
 		restorer = current->mm->context.vdso +
-			selected_vdso32->sym___kernel_sigreturn;
+			vdso_image_32.sym___kernel_sigreturn;
 	else
 		restorer = &frame->retcode;
 	if (ksig->ka.sa.sa_flags & SA_RESTORER)
@@ -363,7 +363,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 
 		/* Set up to return from userspace.  */
 		restorer = current->mm->context.vdso +
-			selected_vdso32->sym___kernel_rt_sigreturn;
+			vdso_image_32.sym___kernel_rt_sigreturn;
 		if (ksig->ka.sa.sa_flags & SA_RESTORER)
 			restorer = ksig->ka.sa.sa_restorer;
 		put_user_ex(restorer, &frame->pretcode);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 55f388e..b166ffd 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -753,17 +753,9 @@ char * __init xen_auto_xlated_memory_setup(void)
 static void __init fiddle_vdso(void)
 {
 #ifdef CONFIG_X86_32
-	/*
-	 * This could be called before selected_vdso32 is initialized, so
-	 * just fiddle with both possible images.  vdso_image_32_syscall
-	 * can't be selected, since it only exists on 64-bit systems.
-	 */
 	u32 *mask;
-	mask = vdso_image_32_int80.data +
-		vdso_image_32_int80.sym_VDSO32_NOTE_MASK;
-	*mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
-	mask = vdso_image_32_sysenter.data +
-		vdso_image_32_sysenter.sym_VDSO32_NOTE_MASK;
+	mask = vdso_image_32.data +
+		vdso_image_32.sym_VDSO32_NOTE_MASK;
 	*mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
 #endif
 }
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ