Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/um: Do not inherit vDSO from host

Inheriting the vDSO from the host is problematic. The values read
from the time functions will not be correct for the UML kernel.
Furthermore the start and end of the vDSO are not stable or
detectable by userspace. Specifically the vDSO datapages start
before AT_SYSINFO_EHDR and the vDSO itself is larger than a single page.

This codepath is only used on 32bit x86 UML. In my testing with both
32bit and 64bit hosts the passthrough functionality has always been
disabled anyways due to the checks against envp in scan_elf_aux().

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251028-uml-remove-32bit-pseudo-vdso-v1-4-e930063eff5f@weissschuh.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Thomas Weißschuh and committed by
Johannes Berg
70d52694 83b4b44a

+3 -139
-27
arch/um/os-Linux/elf_aux.c
··· 20 20 /* These are initialized very early in boot and never changed */ 21 21 char * elf_aux_platform; 22 22 extern long elf_aux_hwcap; 23 - unsigned long vsyscall_ehdr; 24 - unsigned long vsyscall_end; 25 - unsigned long __kernel_vsyscall; 26 23 27 24 __init void scan_elf_aux( char **envp) 28 25 { 29 - long page_size = 0; 30 26 elf_auxv_t * auxv; 31 27 32 28 while ( *envp++ != NULL) ; 33 29 34 30 for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { 35 31 switch ( auxv->a_type ) { 36 - case AT_SYSINFO: 37 - __kernel_vsyscall = auxv->a_un.a_val; 38 - /* See if the page is under TASK_SIZE */ 39 - if (__kernel_vsyscall < (unsigned long) envp) 40 - __kernel_vsyscall = 0; 41 - break; 42 - case AT_SYSINFO_EHDR: 43 - vsyscall_ehdr = auxv->a_un.a_val; 44 - /* See if the page is under TASK_SIZE */ 45 - if (vsyscall_ehdr < (unsigned long) envp) 46 - vsyscall_ehdr = 0; 47 - break; 48 32 case AT_HWCAP: 49 33 elf_aux_hwcap = auxv->a_un.a_val; 50 34 break; ··· 40 56 elf_aux_platform = 41 57 (char *) (long) auxv->a_un.a_val; 42 58 break; 43 - case AT_PAGESZ: 44 - page_size = auxv->a_un.a_val; 45 - break; 46 59 } 47 - } 48 - if ( ! __kernel_vsyscall || ! vsyscall_ehdr || 49 - ! page_size || (vsyscall_ehdr % page_size) ) { 50 - __kernel_vsyscall = 0; 51 - vsyscall_ehdr = 0; 52 - } 53 - else { 54 - vsyscall_end = vsyscall_ehdr + page_size; 55 60 } 56 61 }
-6
arch/um/os-Linux/user_syms.c
··· 31 31 EXPORT_SYMBOL(memset); 32 32 #endif 33 33 34 - #ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA 35 - /* needed for __access_ok() */ 36 - EXPORT_SYMBOL(vsyscall_ehdr); 37 - EXPORT_SYMBOL(vsyscall_end); 38 - #endif 39 - 40 34 #ifdef _FORTIFY_SOURCE 41 35 extern int __sprintf_chk(char *str, int flag, size_t len, const char *format); 42 36 EXPORT_SYMBOL(__sprintf_chk);
-1
arch/x86/um/Kconfig
··· 8 8 9 9 config UML_X86 10 10 def_bool y 11 - select ARCH_BINFMT_ELF_EXTRA_PHDRS if X86_32 12 11 select ARCH_USE_QUEUED_RWLOCKS 13 12 select ARCH_USE_QUEUED_SPINLOCKS 14 13 select DCACHE_WORD_ACCESS
-1
arch/x86/um/Makefile
··· 18 18 ifeq ($(CONFIG_X86_32),y) 19 19 20 20 obj-y += syscalls_32.o 21 - obj-$(CONFIG_ELF_CORE) += elfcore.o 22 21 23 22 subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o 24 23 subarch-y += ../lib/cmpxchg8b_emu.o ../lib/atomic64_386_32.o
+3 -26
arch/x86/um/asm/elf.h
··· 72 72 #define ELF_PLATFORM_FALLBACK "i586" 73 73 #define ELF_PLATFORM (elf_aux_platform ?: ELF_PLATFORM_FALLBACK) 74 74 75 - extern unsigned long vsyscall_ehdr; 76 - extern unsigned long vsyscall_end; 77 - extern unsigned long __kernel_vsyscall; 78 - 79 - /* 80 - * This is the range that is readable by user mode, and things 81 - * acting like user mode such as get_user_pages. 82 - */ 83 - #define FIXADDR_USER_START vsyscall_ehdr 84 - #define FIXADDR_USER_END vsyscall_end 85 - 86 - 87 - /* 88 - * Architecture-neutral AT_ values in 0-17, leave some room 89 - * for more of them, start the x86-specific ones at 32. 90 - */ 91 - #define AT_SYSINFO 32 92 - #define AT_SYSINFO_EHDR 33 93 - 94 - #define ARCH_DLINFO \ 95 - do { \ 96 - if ( vsyscall_ehdr ) { \ 97 - NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall); \ 98 - NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr); \ 99 - } \ 100 - } while (0) 75 + /* No user-accessible fixmap addresses, i.e. vsyscall */ 76 + #define FIXADDR_USER_START 0 77 + #define FIXADDR_USER_END 0 101 78 102 79 #else 103 80
-78
arch/x86/um/elfcore.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/elf.h> 3 - #include <linux/elfcore.h> 4 - #include <linux/coredump.h> 5 - #include <linux/fs.h> 6 - #include <linux/mm.h> 7 - 8 - #include <asm/elf.h> 9 - 10 - 11 - Elf32_Half elf_core_extra_phdrs(struct coredump_params *cprm) 12 - { 13 - return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0; 14 - } 15 - 16 - int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) 17 - { 18 - if ( vsyscall_ehdr ) { 19 - const struct elfhdr *const ehdrp = 20 - (struct elfhdr *) vsyscall_ehdr; 21 - const struct elf_phdr *const phdrp = 22 - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); 23 - int i; 24 - Elf32_Off ofs = 0; 25 - 26 - for (i = 0; i < ehdrp->e_phnum; ++i) { 27 - struct elf_phdr phdr = phdrp[i]; 28 - 29 - if (phdr.p_type == PT_LOAD) { 30 - ofs = phdr.p_offset = offset; 31 - offset += phdr.p_filesz; 32 - } else { 33 - phdr.p_offset += ofs; 34 - } 35 - phdr.p_paddr = 0; /* match other core phdrs */ 36 - if (!dump_emit(cprm, &phdr, sizeof(phdr))) 37 - return 0; 38 - } 39 - } 40 - return 1; 41 - } 42 - 43 - int elf_core_write_extra_data(struct coredump_params *cprm) 44 - { 45 - if ( vsyscall_ehdr ) { 46 - const struct elfhdr *const ehdrp = 47 - (struct elfhdr *) vsyscall_ehdr; 48 - const struct elf_phdr *const phdrp = 49 - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); 50 - int i; 51 - 52 - for (i = 0; i < ehdrp->e_phnum; ++i) { 53 - if (phdrp[i].p_type == PT_LOAD) { 54 - void *addr = (void *) phdrp[i].p_vaddr; 55 - size_t filesz = phdrp[i].p_filesz; 56 - if (!dump_emit(cprm, addr, filesz)) 57 - return 0; 58 - } 59 - } 60 - } 61 - return 1; 62 - } 63 - 64 - size_t elf_core_extra_data_size(struct coredump_params *cprm) 65 - { 66 - if ( vsyscall_ehdr ) { 67 - const struct elfhdr *const ehdrp = 68 - (struct elfhdr *)vsyscall_ehdr; 69 - const struct elf_phdr *const phdrp = 70 - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); 71 - int i; 72 - 73 - for (i = 0; i < ehdrp->e_phnum; ++i) 74 - if (phdrp[i].p_type == PT_LOAD) 75 - return (size_t) phdrp[i].p_filesz; 76 - } 77 - return 0; 78 - }