[PATCH 4/7] x86/vdso32: Build single vdso32 image

From: Brian Gerst
Date: Sat Aug 29 2015 - 11:21:29 EST


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@xxxxxxxxx>
---
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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/