From: Jeff Dike From: Bodo Stroesser This is the first patch of a series of four. These patches allow the use of sysenter-systemcalls in UML if the host support sysenter. Some facts have to be noted: - the sysenter instruction does not save anything, not even the return address. Thus the host-kernel builds a stackframe with an fixed return address for the backjump to the vsyscall-page. All kernels that support sysenter thus must have a vsyscall-page - The hosts vsyscall-page is visible in all memory-contexts on the host, even in those of the processes running on UML. This cannot be changed. So the best way to implement sysenter is to integrate the host's vsyscall-page into UML, if available. This patch creates a new source file containing an UML initialization function. The function scans the Elf-auxiliary vector that is prepared by the host for relevant information about: - vsyscall elf-header - vsyscall entry - machine type (called "platform", e.g. "i586" or "i686") - hardware capabilities These informations are inserted into the Elf-auxiliary-vector that is generated if an UML process calls "execXX()". If the information from the auxiliray-vector is not complete, UML uses the previos default values, with one exception: if the host has no vsyscall-page, UML now does no longer insert AT_SYSINFO or AT_SYSINFO_EHDR elements. (I think, that's better than writing dummies) Since the host's vsyscall-page is always visible to UML processes, this change is enough to let UML with an i686-compiled glibc use sysenter. what's missing: - is_syscall() in SKAS cannot access the code in the vsyscall-page via copy_from_user(), thus singlesteppers still could break out. (Note: that's not new, if someone jumps willingly to the sysenter-entry in the vsyscall-page, he can do that without the patch, too). - a debugger cannot access the code in the vsyscall-page via ptrace( PEEKTEXT, ...) Risks: could there by any feature of the host's processor, that is indicated in the hardware capabilities, but must not be used in UML? Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/kernel/main.c | 4 + 25-akpm/arch/um/kernel/um_arch.c | 5 -- 25-akpm/arch/um/os-Linux/Makefile | 5 +- 25-akpm/arch/um/os-Linux/elf_aux.c | 66 ++++++++++++++++++++++++++++++++ 25-akpm/include/asm-um/archparam-i386.h | 25 ++++++------ 25-akpm/include/asm-um/elf.h | 3 - 6 files changed, 88 insertions(+), 20 deletions(-) diff -puN arch/um/kernel/main.c~uml-add-elf-vsyscall-support arch/um/kernel/main.c --- 25/arch/um/kernel/main.c~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/arch/um/kernel/main.c Fri Dec 3 13:50:26 2004 @@ -81,6 +81,8 @@ static void last_ditch_exit(int sig) extern int uml_exitcode; +extern void scan_elf_aux( char **envp); + int main(int argc, char **argv, char **envp) { char **new_argv; @@ -147,6 +149,8 @@ int main(int argc, char **argv, char **e set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); + scan_elf_aux( envp); + do_uml_initcalls(); ret = linux_main(argc, argv); diff -puN arch/um/kernel/um_arch.c~uml-add-elf-vsyscall-support arch/um/kernel/um_arch.c --- 25/arch/um/kernel/um_arch.c~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/arch/um/kernel/um_arch.c Fri Dec 3 13:50:26 2004 @@ -44,11 +44,6 @@ struct cpuinfo_um boot_cpu_data = { .ipi_pipe = { -1, -1 } }; -/* Placeholder to make UML link until the vsyscall stuff is actually - * implemented - */ -void *__kernel_vsyscall; - unsigned long thread_saved_pc(struct task_struct *task) { return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, diff -puN arch/um/os-Linux/elf_aux.c~uml-add-elf-vsyscall-support arch/um/os-Linux/elf_aux.c --- 25/arch/um/os-Linux/elf_aux.c~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/arch/um/os-Linux/elf_aux.c Fri Dec 3 13:50:26 2004 @@ -0,0 +1,66 @@ +/* + * arch/um/kernel/elf_aux.c + * + * Scan the Elf auxiliary vector provided by the host to extract + * information about vsyscall-page, etc. + * + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com) + */ +#include +#include +#include "init.h" + +#if ELF_CLASS == ELFCLASS32 +typedef Elf32_auxv_t elf_auxv_t; +#else +typedef Elf64_auxv_t elf_auxv_t; +#endif + +char * elf_aux_platform; +long elf_aux_hwcap; + +long vsyscall_ehdr; +long vsyscall_end; + +long __kernel_vsyscall; + + +__init void scan_elf_aux( char **envp) +{ + long page_size = 0; + elf_auxv_t * auxv; + + while ( *envp++ != NULL) ; + + for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { + switch ( auxv->a_type ) { + case AT_SYSINFO: + __kernel_vsyscall = auxv->a_un.a_val; + break; + case AT_SYSINFO_EHDR: + vsyscall_ehdr = auxv->a_un.a_val; + break; + case AT_HWCAP: + elf_aux_hwcap = auxv->a_un.a_val; + break; + case AT_PLATFORM: + elf_aux_platform = auxv->a_un.a_ptr; + break; + case AT_PAGESZ: + page_size = auxv->a_un.a_val; + break; + } + } + if ( ! __kernel_vsyscall || ! vsyscall_ehdr || + ! elf_aux_hwcap || ! elf_aux_platform || + ! page_size || (vsyscall_ehdr % page_size) ) { + __kernel_vsyscall = 0; + vsyscall_ehdr = 0; + elf_aux_hwcap = 0; + elf_aux_platform = "i586"; + } + else { + vsyscall_end = vsyscall_ehdr + page_size; + } +} diff -puN arch/um/os-Linux/Makefile~uml-add-elf-vsyscall-support arch/um/os-Linux/Makefile --- 25/arch/um/os-Linux/Makefile~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/arch/um/os-Linux/Makefile Fri Dec 3 13:50:26 2004 @@ -3,9 +3,10 @@ # Licensed under the GPL # -obj-y = file.o process.o time.o tty.o user_syms.o drivers/ +obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/ -USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file)) +USER_OBJS := elf_aux.o file.o process.o time.o tty.o +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< diff -puN include/asm-um/archparam-i386.h~uml-add-elf-vsyscall-support include/asm-um/archparam-i386.h --- 25/include/asm-um/archparam-i386.h~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/include/asm-um/archparam-i386.h Fri Dec 3 13:50:26 2004 @@ -10,7 +10,8 @@ #include "user.h" -#define ELF_PLATFORM "i586" +extern char * elf_aux_platform; +#define ELF_PLATFORM (elf_aux_platform) #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) @@ -56,15 +57,13 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR pr_reg[16] = PT_REGS_SS(regs); \ } while(0); -#if 0 /* Turn this back on when UML has VSYSCALL working */ -#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL)) -#else -#define VSYSCALL_BASE 0 -#endif - -#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE) -#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall) -extern void *__kernel_vsyscall; + +extern long vsyscall_ehdr; +extern long vsyscall_end; +extern long __kernel_vsyscall; + +#define VSYSCALL_BASE vsyscall_ehdr +#define VSYSCALL_END vsyscall_end /* * Architecture-neutral AT_ values in 0-17, leave some room @@ -75,8 +74,10 @@ extern void *__kernel_vsyscall; #define ARCH_DLINFO \ do { \ - NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \ + if ( vsyscall_ehdr ) { \ + NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr); \ + } \ } while (0) /* diff -puN include/asm-um/elf.h~uml-add-elf-vsyscall-support include/asm-um/elf.h --- 25/include/asm-um/elf.h~uml-add-elf-vsyscall-support Fri Dec 3 13:50:26 2004 +++ 25-akpm/include/asm-um/elf.h Fri Dec 3 13:50:26 2004 @@ -3,7 +3,8 @@ #include "asm/archparam.h" -#define ELF_HWCAP (0) +extern long elf_aux_hwcap; +#define ELF_HWCAP (elf_aux_hwcap) #define SET_PERSONALITY(ex, ibcs2) do ; while(0) _