arm64: Add a compat vDSO
Subsystems (2)
v2 cover arm64: Add a compat vDSO
Hi,
This series adds support for a compat (AArch32) vDSO, providing two userspace functionalities to compat processes:
* "Virtual" time syscalls (gettimeofday and clock_gettime). The implementation is an adaptation of the arm vDSO (vgettimeofday.c), sharing the data page with the 64-bit vDSO.
* sigreturn trampolines, following the example of the 64-bit vDSO (sigreturn.S), but slightly more complicated because we provide A32 and T32 variants for both sigreturn and rt_sigreturn.
The first point brings the performance improvement expected of a vDSO, by implementing time syscalls directly in userspace. The second point allows us to get rid of the compat vector page, at the expense of the kuser helpers (this is one reason for not enabling the compat vDSO by default).
Unfortunately, this time we cannot escape using a 32-bit toolchain. To build the compat VDSO, CONFIG_COMPAT_VDSO must be set *and* CROSS_COMPILE_ARM32 must be defined to the prefix of a 32-bit compiler. Failure to do so will not prevent building the kernel, but a warning will be printed and the compat vDSO will not be built.
Thanks,
Kevin
Changelog v1..v2:
* Rebased on 4.9-rc2. I preserved the spirit of 5a9e3e156ec1 ("arm64:
apply __ro_after_init to some objects") by making the new vdso{,32}_mappings static variables __ro_after_init, and removing pages from struct vdso_mappings.
* Added CONFIG_CROSS_COMPILE_ARM32, on the same principle as CONFIG_CROSS_COMPILE. That may help avoid forgetting to set the variable when building the kernel with CONFIG_COMPAT_VDSO.
Kevin Brodsky (8):
arm64: Refactor vDSO setup
arm64: compat: Add time-related syscall numbers
arm64: compat: Expose offset to registers in sigframes
arm64: compat: Add a 32-bit vDSO
arm64: compat: 32-bit vDSO setup
arm64: elf: Set AT_SYSINFO_EHDR in compat processes
arm64: compat: Use vDSO sigreturn trampolines if available
arm64: Wire up and expose the new compat vDSO
arch/arm64/Kconfig | 26 +++ arch/arm64/Makefile | 28 ++- arch/arm64/include/asm/elf.h | 15 +- arch/arm64/include/asm/signal32.h | 46 +++++ arch/arm64/include/asm/unistd.h | 2 + arch/arm64/include/asm/vdso.h | 3 + arch/arm64/kernel/Makefile | 8 +- arch/arm64/kernel/asm-offsets.c | 13 ++ arch/arm64/kernel/signal32.c | 61 ++----- arch/arm64/kernel/vdso.c | 199 ++++++++++++--------- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 15 files changed, 897 insertions(+), 135 deletions(-) create mode 100644 arch/arm64/kernel/vdso32/Makefile create mode 100644 arch/arm64/kernel/vdso32/sigreturn.S create mode 100644 arch/arm64/kernel/vdso32/vdso.S create mode 100644 arch/arm64/kernel/vdso32/vdso.lds.S create mode 100644 arch/arm64/kernel/vdso32/vgettimeofday.c
Signature · 1 line
2.10.0
RFC PATCH v2 1/8 arm64: Refactor vDSO setup
Move the logic for setting up mappings and pages for the vDSO into static functions with a clear interface. This will allow to reuse the setup code for the future compat vDSO.
--- arch/arm64/kernel/vdso.c | 177 ++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 79 deletions(-)
arch/arm64/kernel/vdso.c +98 -79
@@ -37,8 +37,10 @@#include <asm/vdso.h> #include <asm/vdso_datapage.h> -extern char vdso_start, vdso_end; -static unsigned long vdso_pages__ro_after_init ; +struct vdso_mappings { +unsigned long num_pages; +struct vm_special_mapping data_mapping, code_mapping; +};/* * The vDSO data page.
@@ -49,6 +51,92 @@ static union { }vdso_data_store __page_aligned_data;struct vdso_data *vdso_data = &vdso_data_store.data; +static int __init setup_vdso_mappings (const char *name, +const char *code_start, +const char *code_end, +struct vdso_mappings *mappings) +{ +unsigned long i, num_pages; +struct page **pages; + +if (memcmp (code_start,"\177ELF" ,4 )) { +pr_err ("%s is not a valid ELF object!\n" , name); +return -EINVAL ; + } + + num_pages = (code_end - code_start) >>PAGE_SHIFT ; +pr_info ("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n" , + name, num_pages +1 , num_pages, code_start,1L , vdso_data); + +/* Allocate the vDSO code pages, plus a page for the data. */ + pages =kcalloc (num_pages +1 ,sizeof (struct page *),GFP_KERNEL ); +if (pages ==NULL ) +return -ENOMEM ; + +/* Grab the vDSO data page. */ + pages[0 ] =pfn_to_page (PHYS_PFN (__pa (vdso_data))); + +/* Grab the vDSO code pages. */ +for (i =0 ; i < num_pages; i++) + pages[i +1 ] =pfn_to_page (PHYS_PFN (__pa (code_start)) + i); + +/* Populate the special mapping structures */ + mappings->data_mapping = (struct vm_special_mapping ) { + .name ="[vvar]" , + .pages = &pages[0 ], + }; + + mappings->code_mapping = (struct vm_special_mapping ) { + .name ="[vdso]" , + .pages = &pages[1 ], + }; + + mappings->num_pages = num_pages; +return 0 ; +} + +static int setup_vdso_pages (const struct vdso_mappings *mappings) +{ +struct mm_struct *mm = current->mm; +unsigned long vdso_base, vdso_text_len, vdso_mapping_len; +void *ret; + + vdso_text_len = mappings->num_pages <<PAGE_SHIFT ; +/* Be sure to map the data page */ + vdso_mapping_len = vdso_text_len +PAGE_SIZE ; + +if (down_write_killable (&mm->mmap_sem)) +return -EINTR ; + vdso_base =get_unmapped_area (NULL ,0 , vdso_mapping_len,0 ,0 ); +if (IS_ERR_VALUE (vdso_base)) { + ret =ERR_PTR (vdso_base); + goto up_fail; + } + ret =_install_special_mapping (mm, vdso_base,PAGE_SIZE , +VM_READ |VM_MAYREAD , + &mappings->data_mapping); +if (IS_ERR (ret)) + goto up_fail; + + vdso_base +=PAGE_SIZE ; + mm->context.vdso = (void *)vdso_base; + ret =_install_special_mapping (mm, vdso_base, vdso_text_len, +VM_READ |VM_EXEC | +VM_MAYREAD |VM_MAYWRITE |VM_MAYEXEC , + &mappings->code_mapping); +if (IS_ERR (ret)) + goto up_fail; + + +up_write (&mm->mmap_sem); +return 0 ; + +up_fail: + mm->context.vdso =NULL ; +up_write (&mm->mmap_sem); +return PTR_ERR (ret); +} +#ifdef CONFIG_COMPAT /* * Create and map the vectors page for AArch32 tasks.
@@ -71,11 +159,11 @@ static int __init alloc_vectors_page(void)/* kuser helpers */ memcpy ((void *)vpage +0x1000 - kuser_sz, __kuser_helper_start, - kuser_sz); + kuser_sz);/* sigreturn code */ memcpy ((void *)vpage +AARCH32_KERN_SIGRET_CODE_OFFSET , - __aarch32_sigret_code_start, sigret_sz); + __aarch32_sigret_code_start, sigret_sz);flush_icache_range (vpage, vpage +PAGE_SIZE ); vectors_page[0 ] =virt_to_page (vpage);
@@ -110,90 +198,21 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) }#endif /* CONFIG_COMPAT */ -static struct vm_special_mapping vdso_spec[2 ]__ro_after_init = { - { - .name ="[vvar]" , - }, - { - .name ="[vdso]" , - }, -}; +extern char vdso_start, vdso_end; + +static struct vdso_mappings vdso_mappings__ro_after_init ;static int __init vdso_init (void ) { -int i; -struct page **vdso_pagelist; - -if (memcmp (&vdso_start,"\177ELF" ,4 )) { -pr_err ("vDSO is not a valid ELF object!\n" ); -return -EINVAL ; - } - - vdso_pages = (&vdso_end - &vdso_start) >>PAGE_SHIFT ; -pr_info ("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n" , - vdso_pages +1 , vdso_pages, &vdso_start,1L , vdso_data); - -/* Allocate the vDSO pagelist, plus a page for the data. */ - vdso_pagelist =kcalloc (vdso_pages +1 ,sizeof (struct page *), -GFP_KERNEL ); -if (vdso_pagelist ==NULL ) -return -ENOMEM ; - -/* Grab the vDSO data page. */ - vdso_pagelist[0 ] =pfn_to_page (PHYS_PFN (__pa (vdso_data))); - -/* Grab the vDSO code pages. */ -for (i =0 ; i < vdso_pages; i++) - vdso_pagelist[i +1 ] =pfn_to_page (PHYS_PFN (__pa (&vdso_start)) + i); - - vdso_spec[0 ].pages = &vdso_pagelist[0 ]; - vdso_spec[1 ].pages = &vdso_pagelist[1 ]; - -return 0 ; +return setup_vdso_mappings ("vdso" , &vdso_start, &vdso_end, + &vdso_mappings); }arch_initcall (vdso_init);int arch_setup_additional_pages (struct linux_binprm *bprm,int uses_interp) { -struct mm_struct *mm = current->mm; -unsigned long vdso_base, vdso_text_len, vdso_mapping_len; -void *ret; - - vdso_text_len = vdso_pages <<PAGE_SHIFT ; -/* Be sure to map the data page */ - vdso_mapping_len = vdso_text_len +PAGE_SIZE ; - -if (down_write_killable (&mm->mmap_sem)) -return -EINTR ; - vdso_base =get_unmapped_area (NULL ,0 , vdso_mapping_len,0 ,0 ); -if (IS_ERR_VALUE (vdso_base)) { - ret =ERR_PTR (vdso_base); - goto up_fail; - } - ret =_install_special_mapping (mm, vdso_base,PAGE_SIZE , -VM_READ |VM_MAYREAD , - &vdso_spec[0 ]); -if (IS_ERR (ret)) - goto up_fail; - - vdso_base +=PAGE_SIZE ; - mm->context.vdso = (void *)vdso_base; - ret =_install_special_mapping (mm, vdso_base, vdso_text_len, -VM_READ |VM_EXEC | -VM_MAYREAD |VM_MAYWRITE |VM_MAYEXEC , - &vdso_spec[1 ]); -if (IS_ERR (ret)) - goto up_fail; - - -up_write (&mm->mmap_sem); -return 0 ; - -up_fail: - mm->context.vdso =NULL ; -up_write (&mm->mmap_sem); -return PTR_ERR (ret); +return setup_vdso_pages (&vdso_mappings); }/*
Signature · 1 line
2.10.0
RFC PATCH v2 2/8 arm64: compat: Add time-related syscall numbers
In reply to Kevin BrodskyThey will be used by the future compat vDSO.
The compat syscall numbers correspond to the arm syscall numbers, see arch/arm/include/uapi/asm/unistd.h.
--- arch/arm64/include/asm/unistd.h | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/include/asm/unistd.h +2 -0
@@ -34,8 +34,10 @@#define __NR_compat_exit 1#define __NR_compat_read 3#define __NR_compat_write 4 +#define __NR_compat_gettimeofday 78#define __NR_compat_sigreturn 119#define __NR_compat_rt_sigreturn 173 +#define __NR_compat_clock_gettime 263/* * The following SVCs are ARM private.
Signature · 1 line
2.10.0
RFC PATCH v2 3/8 arm64: compat: Expose offset to registers in sigframes
In reply to Kevin BrodskyThis will be needed to provide debug information (CFI/unwind tables) in compat sigreturn trampolines, part of the future compat vDSO.
Also fix minor style issues reported by checkpatch.
--- arch/arm64/include/asm/signal32.h | 46 +++++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/asm-offsets.c | 13 +++++++++++ arch/arm64/kernel/signal32.c | 46 --------------------------------------- 3 files changed, 59 insertions(+), 46 deletions(-)
arch/arm64/include/asm/signal32.h +46 -0
@@ -20,6 +20,52 @@#ifdef CONFIG_COMPAT #include <linux/compat.h> +struct compat_sigcontext { +/* We always set these two fields to 0 */ +compat_ulong_t trap_no; +compat_ulong_t error_code; + +compat_ulong_t oldmask; +compat_ulong_t arm_r0; +compat_ulong_t arm_r1; +compat_ulong_t arm_r2; +compat_ulong_t arm_r3; +compat_ulong_t arm_r4; +compat_ulong_t arm_r5; +compat_ulong_t arm_r6; +compat_ulong_t arm_r7; +compat_ulong_t arm_r8; +compat_ulong_t arm_r9; +compat_ulong_t arm_r10; +compat_ulong_t arm_fp; +compat_ulong_t arm_ip; +compat_ulong_t arm_sp; +compat_ulong_t arm_lr; +compat_ulong_t arm_pc; +compat_ulong_t arm_cpsr; +compat_ulong_t fault_address; +}; + +struct compat_ucontext { +compat_ulong_t uc_flags; +compat_uptr_t uc_link; +compat_stack_t uc_stack; +struct compat_sigcontext uc_mcontext; +compat_sigset_t uc_sigmask; +int __unused[32 - (sizeof (compat_sigset_t) /sizeof (int ))]; +compat_ulong_t uc_regspace[128 ]__aligned(8) ; +}; + +struct compat_sigframe { +struct compat_ucontext uc; +compat_ulong_t retcode[2 ]; +}; + +struct compat_rt_sigframe { +struct compat_siginfo info; +struct compat_sigframe sig; +}; +#define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500extern const compat_ulong_t aarch32_sigret_code[6 ];
arch/arm64/kernel/asm-offsets.c +13 -0
@@ -26,6 +26,7 @@#include <asm/cpufeature.h> #include <asm/thread_info.h> #include <asm/memory.h> +#include <asm/signal32.h> #include <asm/smp_plat.h> #include <asm/suspend.h> #include <asm/vdso_datapage.h>
@@ -75,6 +76,18 @@ int main(void)DEFINE (S_ORIG_ADDR_LIMIT , offsetof(struct pt_regs , orig_addr_limit));DEFINE (S_FRAME_SIZE ,sizeof (struct pt_regs ));BLANK (); +#ifdef CONFIG_COMPAT +DEFINE (COMPAT_SIGFRAME_REGS_OFFSET , + offsetof(struct compat_sigframe , uc) + + offsetof(struct compat_ucontext , uc_mcontext) + + offsetof(struct compat_sigcontext , arm_r0)); +DEFINE (COMPAT_RT_SIGFRAME_REGS_OFFSET , + offsetof(struct compat_rt_sigframe , sig) + + offsetof(struct compat_sigframe , uc) + + offsetof(struct compat_ucontext , uc_mcontext) + + offsetof(struct compat_sigcontext , arm_r0)); +BLANK (); +#endif DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter));BLANK ();DEFINE (VMA_VM_MM , offsetof(struct vm_area_struct , vm_mm));
arch/arm64/kernel/signal32.c +0 -46
58 lines not on this page · raw message
Signature · 1 line
2.10.0
RFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
In reply to Kevin BrodskyProvide the files necessary for building a compat (AArch32) vDSO in kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant change in vgettimeofday.c is the use of the arm64 vdso_data struct, allowing the vDSO data page to be shared between the 32 and 64-bit vDSOs.
In addition to the time functions, sigreturn trampolines are also provided, aiming at replacing those in the vector page. To improve debugging, CFI and unwinding directives are used, based on glibc's implementation. Symbol offsets are made available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat to all this: we cannot get away with hand-coding 32-bit instructions like in kernel/kuser32.S, this time we really need a 32-bit compiler. The compat vDSO Makefile relies on CROSS_COMPILE_ARM32 to provide a 32-bit compiler, appropriate logic will be added to the arm64 Makefile later on to ensure that an attempt to build the compat vDSO is made only if this variable has been set properly.
--- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 5 files changed, 631 insertions(+) create mode 100644 arch/arm64/kernel/vdso32/Makefile create mode 100644 arch/arm64/kernel/vdso32/sigreturn.S create mode 100644 arch/arm64/kernel/vdso32/vdso.S create mode 100644 arch/arm64/kernel/vdso32/vdso.lds.S create mode 100644 arch/arm64/kernel/vdso32/vgettimeofday.c
arch/arm64/kernel/vdso32/Makefile new file +121 -0
@@ -0,0 +1,121 @@ +# +# Building a vDSO image for AArch32. +# +# Author: Kevin Brodsky <[email protected]> +# A mix between the arm64 and arm vDSO Makefiles. + +CC_ARM32 := $(CROSS_COMPILE_ARM32)gcc + +# Same as cc-ldoption, but using CC_ARM32 instead of CC +cc32-ldoption = $(call try-run,\ + $(CC_ARM32) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) + +# Borrow vdsomunge.c from the arm vDSO +munge := arch/arm/vdso/vdsomunge +hostprogs-y := $(srctree)/$(munge) + +c-obj-vdso := vgettimeofday.o +asm-obj-vdso := sigreturn.o + +# Build rules +targets := $(c-obj-vdso) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw +c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) +asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) +obj-vdso := $(c-obj-vdso) $(asm-obj-vdso) + +ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protector +ccflags-y += -DDISABLE_BRANCH_PROFILING + +# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2 +# Import some useful flags from arch/arm/Makefile +VDSO_CFLAGS += -mabi=aapcs-linux -mfloat-abi=soft -funwind-tables +# The 32-bit compiler does not provide 128-bit integers, which are used in +# some headers that are indirectly included from the vDSO code. +# This hack makes the compiler happy and should trigger a warning/error if +# variables of such type are referenced. +VDSO_CFLAGS += -D__uint128_t='void*' +# Silence some warnings coming from headers that operate on long's +VDSO_CFLAGS += -Wno-shift-count-overflow -Wno-int-to-pointer-cast + +# We need to use the global flags to compile the vDSO files. However some flags +# inherited from either the top-level or the arm64 Makefile are not appropriate +# for the 32-bit compiler, this function takes care of changing them as +# appropriate. +sanitize_flags = \ + $(subst $(shell $(CC) -print-file-name=include), \ + $(shell $(CC_ARM32) -print-file-name=include), \ + $(filter-out -pg -mgeneral-regs-only -mpc-relative-literal-loads \ + -fno-asynchronous-unwind-tables, \ + $(1))) + +VDSO_LDFLAGS := -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 +VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 +VDSO_LDFLAGS += -nostdlib -shared -mfloat-abi=soft +VDSO_LDFLAGS += $(call cc32-ldoption, -Wl$(comma)--hash-style=sysv) +VDSO_LDFLAGS += $(call cc32-ldoption, -Wl$(comma)--build-id) +VDSO_LDFLAGS += $(call cc32-ldoption, -fuse-ld=bfd) + +obj-y += vdso.o +extra-y += vdso.lds +CPPFLAGS_vdso.lds += -P -C -U$(ARCH) + +CFLAGS_REMOVE_vdso.o = -pg + +# Disable gcov profiling for VDSO code +GCOV_PROFILE := n + +# Force dependency (incbin is bad) +$(obj)/vdso.o: $(obj)/vdso.so + +# Link rule for the .so file, .lds has to be first +$(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE + $(call if_changed,vdsold) + +$(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(objtree)/$(munge) FORCE + $(call if_changed,vdsomunge) + +# Strip rule for the .so file +$(obj)/%.so: OBJCOPYFLAGS := -S +$(obj)/%.so: $(obj)/%.so.dbg FORCE + $(call if_changed,objcopy) + +# Generate vDSO offsets using helper script (borrowed from the 64-bit vDSO) +gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh +quiet_cmd_vdsosym = VDSOSYM $@ +# The AArch64 nm should be able to read an AArch32 binary +define cmd_vdsosym + $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ +endef + +include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE + $(call if_changed,vdsosym) + +# Compilation rules for the vDSO sources +$(c-obj-vdso): %.o: %.c FORCE + $(call if_changed_dep,vdsocc) +$(asm-obj-vdso): %.o: %.S FORCE + $(call if_changed_dep,vdsoas) + +# Actual build commands +quiet_cmd_vdsold = VDSOL $@ + cmd_vdsold = $(CC_ARM32) $(call sanitize_flags,$(c_flags)) \ + $(VDSO_LDFLAGS) -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@ +quiet_cmd_vdsocc = VDSOC $@ + cmd_vdsocc = $(CC_ARM32) $(call sanitize_flags,$(c_flags)) \ + $(VDSO_CFLAGS) -c -o $@ $< +quiet_cmd_vdsoas = VDSOA $@ + cmd_vdsoas = $(CC_ARM32) $(call sanitize_flags, $(a_flags)) -c -o $@ $< + +quiet_cmd_vdsomunge = MUNGE $@ + cmd_vdsomunge = $(objtree)/$(munge) $< $@ + +# Install commands for the unstripped file +quiet_cmd_vdso_install = INSTALL $@ + cmd_vdso_install = cp $(obj)/[email protected] $(MODLIB)/vdso/vdso32.so + +vdso.so: $(obj)/vdso.so.dbg + @mkdir -p $(MODLIB)/vdso + $(call cmd,vdso_install) + +vdso_install: vdso.so
arch/arm64/kernel/vdso32/sigreturn.S new file +86 -0
86 lines not on this page · raw message
arch/arm64/kernel/vdso32/vdso.S new file +32 -0
@@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Will Deacon <[email protected]> + */ + +#include <linux/init.h> +#include <linux/linkage.h> +#include <linux/const.h> +#include <asm/page.h> + + .globl vdso32_start, vdso32_end + .section .rodata + .balign PAGE_SIZE +vdso32_start: + .incbin "arch/arm64/kernel/vdso32/vdso.so" + .balign PAGE_SIZE +vdso32_end: + + .previous
arch/arm64/kernel/vdso32/vdso.lds.S new file +98 -0
98 lines not on this page · raw message
arch/arm64/kernel/vdso32/vgettimeofday.c new file +294 -0
294 lines not on this page · raw message
Signature · 1 line
2.10.0
RFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Dear Kevin,
Quoted 62 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
Provide the files necessary for building a compat (AArch32) vDSO in kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant change in
vgettimeofday.cis the use of the arm64vdso_datastruct, allowing the vDSO data page to be shared between the 32 and 64-bit vDSOs.In addition to the time functions, sigreturn trampolines are also provided, aiming at replacing those in the vector page. To improve debugging, CFI and unwinding directives are used, based on glibc's implementation. Symbol offsets are made available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat to all this: we cannot get away with hand-coding 32-bit instructions like in
kernel/kuser32.S, this time we really need a 32-bit compiler. The compat vDSOMakefilerelies onCROSS_COMPILE_ARM32to provide a 32-bit compiler, appropriate logic will be added to the arm64Makefilelater on to ensure that an attempt to build the compat vDSO is made only if this variable has been set properly.Signed-off-by Kevin Brodsky <[email protected]>--- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 5 files changed, 631 insertions(+) create mode 100644 arch/arm64/kernel/vdso32/Makefile create mode 100644 arch/arm64/kernel/vdso32/sigreturn.S create mode 100644 arch/arm64/kernel/vdso32/vdso.S create mode 100644 arch/arm64/kernel/vdso32/vdso.lds.S create mode 100644 arch/arm64/kernel/vdso32/vgettimeofday.carch/arm64/kernel/vdso32/Makefile new file +20
-0@@ -0,0 +1,121 @@ +# +# Building a vDSO image for AArch32. +# +# Author: Kevin Brodsky <[email protected]> +# A mix between the arm64 and arm vDSO Makefiles. + +CC_ARM32 := $(CROSS_COMPILE_ARM32)gcc + +# Same as cc-ldoption, but using CC_ARM32 instead of CC +cc32-ldoption = $(call try-run,\ + $(CC_ARM32) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) + +# Borrow vdsomunge.c from the arm vDSO +munge := arch/arm/vdso/vdsomunge +hostprogs-y := $(srctree)/$(munge) + +c-obj-vdso := vgettimeofday.o +asm-obj-vdso := sigreturn.o + +# Build rules
arch/arm64/kernel/vdso32/Makefile line 30
Quoted 10 lines
arch/arm64/kernel/vdso32/Makefile new file +10
-0+targets := $(c-obj-vdso) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw +c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) +asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) +obj-vdso := $(c-obj-vdso) $(asm-obj-vdso) + +ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protector +ccflags-y += -DDISABLE_BRANCH_PROFILING + +# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2
For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?
Thanks,
Jisheng
RFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Quoted 81 lines · Jisheng Zhang
Dear Kevin,
Quoted 62 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
Provide the files necessary for building a compat (AArch32) vDSO in kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant change in
vgettimeofday.cis the use of the arm64vdso_datastruct, allowing the vDSO data page to be shared between the 32 and 64-bit vDSOs.In addition to the time functions, sigreturn trampolines are also provided, aiming at replacing those in the vector page. To improve debugging, CFI and unwinding directives are used, based on glibc's implementation. Symbol offsets are made available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat to all this: we cannot get away with hand-coding 32-bit instructions like in
kernel/kuser32.S, this time we really need a 32-bit compiler. The compat vDSOMakefilerelies onCROSS_COMPILE_ARM32to provide a 32-bit compiler, appropriate logic will be added to the arm64Makefilelater on to ensure that an attempt to build the compat vDSO is made only if this variable has been set properly.Signed-off-by Kevin Brodsky <[email protected]>--- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 5 files changed, 631 insertions(+)create mode 100644
arch/arm64/kernel/vdso32/Makefilecreate mode 100644arch/arm64/kernel/vdso32/sigreturn.Screate mode 100644arch/arm64/kernel/vdso32/vdso.Screate mode 100644arch/arm64/kernel/vdso32/vdso.lds.Screate mode 100644arch/arm64/kernel/vdso32/vgettimeofday.carch/arm64/kernel/vdso32/Makefile new file +20
-0@@ -0,0 +1,121 @@ +# +# Building a vDSO image for AArch32. +# +# Author: Kevin Brodsky <[email protected]> +# A mix between the arm64 and arm vDSO Makefiles. + +CC_ARM32 := $(CROSS_COMPILE_ARM32)gcc + +# Same as cc-ldoption, but using CC_ARM32 instead of CC +cc32-ldoption = $(call try-run,\ + $(CC_ARM32) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) + +# Borrow vdsomunge.c from the arm vDSO +munge := arch/arm/vdso/vdsomunge +hostprogs-y := $(srctree)/$(munge) + +c-obj-vdso := vgettimeofday.o +asm-obj-vdso := sigreturn.o + +# Build rulesarch/arm64/kernel/vdso32/Makefile line 30
Quoted 10 lines
arch/arm64/kernel/vdso32/Makefile new file +10
-0+targets := $(c-obj-vdso) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw +c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) +asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) +obj-vdso := $(c-obj-vdso) $(asm-obj-vdso) + +ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protector +ccflags-y += -DDISABLE_BRANCH_PROFILING + +# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?
Quoted 2 lines
Thanks,
Jisheng
That's a fair point. I guess -march=armv8-a is not strictly necessary and the produced vDSO should be fine if arch/arm/vdso also compiles fine. However we would still need to pass -march=armv7-a. I'm not sure what to do between:
* Checking that the compiler supports -march=armv8-a when inspecting CROSS_COMPILE_ARM32, and if it doesn't vdso32 will not be built.
* Checking whether -march=armv8-a is available here, and if it is not fall back to -march=armv7-a.
Thanks!
Kevin
Catalin Marinas
maintainerRFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Quoted 79 lines · Kevin Brodsky
Quoted 69 lines · Jisheng Zhang
Quoted 68 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
Provide the files necessary for building a compat (AArch32) vDSO in kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant change in
vgettimeofday.cis the use of the arm64vdso_datastruct, allowing the vDSO data page to be shared between the 32 and 64-bit vDSOs.In addition to the time functions, sigreturn trampolines are also provided, aiming at replacing those in the vector page. To improve debugging, CFI and unwinding directives are used, based on glibc's implementation. Symbol offsets are made available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat to all this: we cannot get away with hand-coding 32-bit instructions like in
kernel/kuser32.S, this time we really need a 32-bit compiler. The compat vDSOMakefilerelies onCROSS_COMPILE_ARM32to provide a 32-bit compiler, appropriate logic will be added to the arm64Makefilelater on to ensure that an attempt to build the compat vDSO is made only if this variable has been set properly.Signed-off-by Kevin Brodsky <[email protected]>--- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 5 files changed, 631 insertions(+)create mode 100644
arch/arm64/kernel/vdso32/Makefilecreate mode 100644arch/arm64/kernel/vdso32/sigreturn.Screate mode 100644arch/arm64/kernel/vdso32/vdso.Screate mode 100644arch/arm64/kernel/vdso32/vdso.lds.Screate mode 100644arch/arm64/kernel/vdso32/vgettimeofday.carch/arm64/kernel/vdso32/Makefile new file +26
-0@@ -0,0 +1,121 @@ +# +# Building a vDSO image for AArch32. +# +# Author: Kevin Brodsky <[email protected]> +# A mix between the arm64 and arm vDSO Makefiles. + +CC_ARM32 := $(CROSS_COMPILE_ARM32)gcc + +# Same as cc-ldoption, but using CC_ARM32 instead of CC +cc32-ldoption = $(call try-run,\ + $(CC_ARM32) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) + +# Borrow vdsomunge.c from the arm vDSO +munge := arch/arm/vdso/vdsomunge +hostprogs-y := $(srctree)/$(munge) + +c-obj-vdso := vgettimeofday.o +asm-obj-vdso := sigreturn.o + +# Build rules +targets := $(c-obj-vdso) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw +c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) +asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) +obj-vdso := $(c-obj-vdso) $(asm-obj-vdso) + +ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protectorQuoted 8 lines
arch/arm64/kernel/vdso32/Makefile line 30
Quoted 4 lines
arch/arm64/kernel/vdso32/Makefile new file +4
-0+ccflags-y += -DDISABLE_BRANCH_PROFILING + +# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?
Quoted 8 lines
That's a fair point. I guess -march=armv8-a is not strictly necessary and the produced vDSO should be fine if
arch/arm/vdsoalso compiles fine. However we would still need to pass -march=armv7-a. I'm not sure what to do between:
* Checking that the compiler supports -march=armv8-a when inspectingCROSS_COMPILE_ARM32, and if it doesn't vdso32 will not be built.
* Checking whether -march=armv8-a is available here, and if it is not fall back to -march=armv7-a.
Does v8 vs v7 make any difference in the generated code? If not, we could just stick to armv7-a permanently.
Signature · 1 line
Catalin
RFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Quoted 87 lines · Catalin Marinas
Quoted 78 lines · Kevin Brodsky
Quoted 69 lines · Jisheng Zhang
Quoted 68 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
Provide the files necessary for building a compat (AArch32) vDSO in kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant change in
vgettimeofday.cis the use of the arm64vdso_datastruct, allowing the vDSO data page to be shared between the 32 and 64-bit vDSOs.In addition to the time functions, sigreturn trampolines are also provided, aiming at replacing those in the vector page. To improve debugging, CFI and unwinding directives are used, based on glibc's implementation. Symbol offsets are made available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat to all this: we cannot get away with hand-coding 32-bit instructions like in
kernel/kuser32.S, this time we really need a 32-bit compiler. The compat vDSOMakefilerelies onCROSS_COMPILE_ARM32to provide a 32-bit compiler, appropriate logic will be added to the arm64Makefilelater on to ensure that an attempt to build the compat vDSO is made only if this variable has been set properly.Signed-off-by Kevin Brodsky <[email protected]>--- arch/arm64/kernel/vdso32/Makefile | 121 +++++++++++++ arch/arm64/kernel/vdso32/sigreturn.S | 86 +++++++++ arch/arm64/kernel/vdso32/vdso.S | 32 ++++ arch/arm64/kernel/vdso32/vdso.lds.S | 98 +++++++++++ arch/arm64/kernel/vdso32/vgettimeofday.c | 294 +++++++++++++++++++++++++++++++ 5 files changed, 631 insertions(+)create mode 100644
arch/arm64/kernel/vdso32/Makefilecreate mode 100644arch/arm64/kernel/vdso32/sigreturn.Screate mode 100644arch/arm64/kernel/vdso32/vdso.Screate mode 100644arch/arm64/kernel/vdso32/vdso.lds.Screate mode 100644arch/arm64/kernel/vdso32/vgettimeofday.carch/arm64/kernel/vdso32/Makefile new file +26
-0@@ -0,0 +1,121 @@ +# +# Building a vDSO image for AArch32. +# +# Author: Kevin Brodsky <[email protected]> +# A mix between the arm64 and arm vDSO Makefiles. + +CC_ARM32 := $(CROSS_COMPILE_ARM32)gcc + +# Same as cc-ldoption, but using CC_ARM32 instead of CC +cc32-ldoption = $(call try-run,\ + $(CC_ARM32) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) + +# Borrow vdsomunge.c from the arm vDSO +munge := arch/arm/vdso/vdsomunge +hostprogs-y := $(srctree)/$(munge) + +c-obj-vdso := vgettimeofday.o +asm-obj-vdso := sigreturn.o + +# Build rules +targets := $(c-obj-vdso) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw +c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) +asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) +obj-vdso := $(c-obj-vdso) $(asm-obj-vdso) + +ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protectorQuoted 8 lines
arch/arm64/kernel/vdso32/Makefile line 30
Quoted 4 lines
arch/arm64/kernel/vdso32/Makefile new file +4
-0+ccflags-y += -DDISABLE_BRANCH_PROFILING + +# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?Quoted 8 lines
That's a fair point. I guess -march=armv8-a is not strictly necessary and the produced vDSO should be fine if
arch/arm/vdsoalso compiles fine. However we would still need to pass -march=armv7-a. I'm not sure what to do between:
* Checking that the compiler supports -march=armv8-a when inspectingCROSS_COMPILE_ARM32, and if it doesn't vdso32 will not be built.
* Checking whether -march=armv8-a is available here, and if it is not fall back to -march=armv7-a.
Quoted 2 lines
Does v8 vs v7 make any difference in the generated code? If not, we could just stick to armv7-a permanently.
I've just tried compiling with -march=armv7-a, and in fact it doesn't compile at all. It turns out vgettimeofday.c uses smp_rmb(), which expands to dmb ishld on arm64, and ishld doesn't exist in ARMv7. We could possibly work around that, but I think requiring GCC 4.8 is reasonable.
Thanks,
Kevin
Catalin Marinas
maintainerRFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Quoted 21 lines · Kevin Brodsky
Quoted 20 lines · Catalin Marinas
Quoted 18 lines · Kevin Brodsky
Quoted 8 lines · Jisheng Zhang
arch/arm64/kernel/vdso32/Makefile line 30
Quoted 2 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
arch/arm64/kernel/vdso32/Makefile new file +2
-0+# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?That's a fair point. I guess -march=armv8-a is not strictly necessary and the produced vDSO should be fine if
arch/arm/vdsoalso compiles fine. However we would still need to pass -march=armv7-a. I'm not sure what to do between:
* Checking that the compiler supports -march=armv8-a when inspectingCROSS_COMPILE_ARM32, and if it doesn't vdso32 will not be built.
* Checking whether -march=armv8-a is available here, and if it is not fall back to -march=armv7-a.
Quoted 7 lines
Quoted 2 lines
Does v8 vs v7 make any difference in the generated code? If not, we could just stick to armv7-a permanently.
I've just tried compiling with -march=armv7-a, and in fact it doesn't compile at all. It turns out
vgettimeofday.cusessmp_rmb(), which expands to dmb ishld on arm64, and ishld doesn't exist in ARMv7. We could possibly work around that, but I think requiring GCC 4.8 is reasonable.
Since vgettimeofday.c is meant to be compiled for AArch32, it wouldn't look too bad to define its own barriers rather than relying on the AArch64 ones. So you could define v7_smp_rmb/v7_smp_wmb and use them in this file. Alternatively, replace smp_rmb() with smp_mb() in this file but with a big comment about ARMv7 compilation requirement and "ishld" not being available.
Signature · 1 line
Catalin
RFC PATCH v2 4/8 arm64: compat: Add a 32-bit vDSO
Quoted 25 lines · Catalin Marinas
Quoted 18 lines · Kevin Brodsky
Quoted 17 lines · Catalin Marinas
Quoted 16 lines · Kevin Brodsky
Quoted 7 lines · Jisheng Zhang
arch/arm64/kernel/vdso32/Makefile line 30
Quoted 2 lines · On Thu, 27 Oct 2016 17:30:54 +0100 Kevin Brodsky wrote:
arch/arm64/kernel/vdso32/Makefile new file +2
-0+# Force -O2 to avoid libgcc dependencies +VDSO_CFLAGS := -march=armv8-a -O2For completeness, bringing 32bit compiler need to check whether the 32bit toolchain support some options. IIRC, armv8-a support isn't enabled until gcc 4.8, so old toolchains such gcc-4.7 will complain:
error: unrecognized argument in option ?-march=armv8-a?That's a fair point. I guess -march=armv8-a is not strictly necessary and the produced vDSO should be fine if
arch/arm/vdsoalso compiles fine. However we would still need to pass -march=armv7-a. I'm not sure what to do between:
* Checking that the compiler supports -march=armv8-a when inspectingCROSS_COMPILE_ARM32, and if it doesn't vdso32 will not be built.
* Checking whether -march=armv8-a is available here, and if it is not fall back to -march=armv7-a.Quoted 6 lines
Quoted 2 lines
Does v8 vs v7 make any difference in the generated code? If not, we could just stick to armv7-a permanently.
I've just tried compiling with -march=armv7-a, and in fact it doesn't compile at all. It turns out
vgettimeofday.cusessmp_rmb(), which expands to dmb ishld on arm64, and ishld doesn't exist in ARMv7. We could possibly work around that, but I think requiring GCC 4.8 is reasonable.
Quoted 6 lines
Since
vgettimeofday.cis meant to be compiled for AArch32, it wouldn't look too bad to define its own barriers rather than relying on the AArch64 ones. So you could define v7_smp_rmb/v7_smp_wmb and use them in this file. Alternatively, replacesmp_rmb()withsmp_mb()in this file but with a big comment about ARMv7 compilation requirement and "ishld" not being available.
Fair enough. I'll add AArch32 barrier macros and compile with -march=armv7-a if the compiler doesn't support armv8-a. It's true that using arm64 barrier macros in 32-bit code is a bit dodgy anyway.
Cheers,
Kevin
RFC PATCH v2 5/8 arm64: compat: 32-bit vDSO setup
In reply to Kevin BrodskyIf the compat vDSO is enabled, install it in compat processes. In this case, the compat vDSO replaces the vector page.
aarch32_setup_vectors_page has also been renamed to the more generic aarch32_setup_additional_pages to reflect both use cases.
--- arch/arm64/include/asm/elf.h | 6 +++--- arch/arm64/kernel/vdso.c | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-)
arch/arm64/include/asm/elf.h +3 -3
@@ -185,10 +185,10 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];#define compat_start_thread compat_start_thread#define COMPAT_SET_PERSONALITY (ex) set_thread_flag(TIF_32BIT);#define COMPAT_ARCH_DLINFO -extern int aarch32_setup_vectors_page (struct linux_binprm *bprm, -int uses_interp); +extern int aarch32_setup_additional_pages (struct linux_binprm *bprm, +int uses_interp);#define compat_arch_setup_additional_pages \ - aarch32_setup_vectors_page + aarch32_setup_additional_pages#endif /* CONFIG_COMPAT */
arch/arm64/kernel/vdso.c +21 -1
@@ -138,6 +138,25 @@ static int setup_vdso_pages(const struct vdso_mappings *mappings) }#ifdef CONFIG_COMPAT +#ifdef CONFIG_VDSO32 +extern char vdso32_start, vdso32_end; + +static struct vdso_mappings vdso32_mappings__ro_after_init ; + +static int __init vdso32_init (void ) +{ +return setup_vdso_mappings ("vdso32" , &vdso32_start, &vdso32_end, + &vdso32_mappings); +} +arch_initcall (vdso32_init); + +int aarch32_setup_additional_pages (struct linux_binprm *bprm,int uses_interp) +{ +return setup_vdso_pages (&vdso32_mappings); +} + +#else /* CONFIG_VDSO32 */ +/* * Create and map the vectors page for AArch32 tasks. */
@@ -172,7 +191,7 @@ static int __init alloc_vectors_page(void) }arch_initcall (alloc_vectors_page); -int aarch32_setup_vectors_page (struct linux_binprm *bprm,int uses_interp) +int aarch32_setup_additional_pages (struct linux_binprm *bprm,int uses_interp) {struct mm_struct *mm = current->mm;unsigned long addr =AARCH32_VECTORS_BASE ;
@@ -196,6 +215,7 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)return PTR_ERR_OR_ZERO (ret); } +#endif /* CONFIG_VDSO32 */ #endif /* CONFIG_COMPAT */ extern char vdso_start, vdso_end;
Signature · 1 line
2.10.0
RFC PATCH v2 6/8 arm64: elf: Set AT_SYSINFO_EHDR in compat processes
In reply to Kevin BrodskyIf the compat vDSO is enabled, we need to set AT_SYSINFO_EHDR in the auxiliary vector of compat processes to the address of the vDSO code page, so that the dynamic linker can find it (just like the regular vDSO).
Note that we cast context.vdso to unsigned long, instead of elf_addr_t, because elf_addr_t is 32-bit in compat_binfmt_elf.c, and casting to u32 would trigger a pointer narrowing warning.
--- arch/arm64/include/asm/elf.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/arm64/include/asm/elf.h +7 -2
@@ -141,11 +141,12 @@ typedef struct user_fpsimd_state elf_fpregset_t;#define SET_PERSONALITY (ex) clear_thread_flag(TIF_32BIT);/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ -#define ARCH_DLINFO \ +#define _SET_AUX_ENT_VDSO \ do { \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (elf_addr_t)current->mm->context.vdso); \ + (unsigned long)current->mm->context.vdso); \ } while (0) +#define ARCH_DLINFO _SET_AUX_ENT_VDSO#define ARCH_HAS_SETUP_ADDITIONAL_PAGES struct linux_binprm ;
@@ -184,7 +185,11 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];#define compat_start_thread compat_start_thread#define COMPAT_SET_PERSONALITY (ex) set_thread_flag(TIF_32BIT); +#ifdef CONFIG_VDSO32 +#define COMPAT_ARCH_DLINFO _SET_AUX_ENT_VDSO +#else #define COMPAT_ARCH_DLINFO +#endif extern int aarch32_setup_additional_pages (struct linux_binprm *bprm,int uses_interp);#define compat_arch_setup_additional_pages \
Signature · 1 line
2.10.0
RFC PATCH v2 7/8 arm64: compat: Use vDSO sigreturn trampolines if available
In reply to Kevin BrodskyIf the compat vDSO is enabled, it replaces the vector page. Therefore, we use the sigreturn trampolines it provides instead of those in the vector page.
--- arch/arm64/include/asm/vdso.h | 3 +++ arch/arm64/kernel/signal32.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+)
arch/arm64/include/asm/vdso.h +3 -0
@@ -28,6 +28,9 @@#ifndef __ASSEMBLY__#include <generated/vdso-offsets.h> +#ifdef CONFIG_VDSO32 +#include <generated/vdso32-offsets.h> +#endif #define VDSO_SYMBOL (base, name) \ ({ \
arch/arm64/kernel/signal32.c +15 -0
@@ -28,6 +28,7 @@#include <asm/signal32.h> #include <asm/uaccess.h> #include <asm/unistd.h> +#include <asm/vdso.h> struct compat_vfp_sigframe {compat_ulong_t magic;
@@ -438,6 +439,19 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, retcode =ptr_to_compat (ka->sa.sa_restorer); }else {/* Set up sigreturn pointer */ +#ifdef CONFIG_VDSO32 +void *vdso_page = current->mm->context.vdso; +void *trampoline = + (ka->sa.sa_flags &SA_SIGINFO + ? (thumb + ?VDSO_SYMBOL (vdso_page, compat_rt_sigreturn_thumb) + :VDSO_SYMBOL (vdso_page, compat_rt_sigreturn_arm)) + : (thumb + ?VDSO_SYMBOL (vdso_page, compat_sigreturn_thumb) + :VDSO_SYMBOL (vdso_page, compat_sigreturn_arm))); + + retcode =ptr_to_compat (trampoline) + thumb; +#else unsigned int idx = thumb <<1 ;if (ka->sa.sa_flags &SA_SIGINFO )
@@ -446,6 +460,7 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, retcode =AARCH32_VECTORS_BASE +AARCH32_KERN_SIGRET_CODE_OFFSET + (idx <<2 ) + thumb; +#endif } regs->regs[0 ] = usig;
Signature · 1 line
2.10.0
RFC PATCH v2 8/8 arm64: Wire up and expose the new compat vDSO
In reply to Kevin BrodskyExpose the new compat vDSO via the COMPAT_VDSO config option.
The option is not enabled in defconfig for two reasons:
* The vDSO page replaces the vector page. The vDSO provides its own sigreturn trampolines, replacing those in the vector page, but the kuser helpers are gone. As a result enabling the compat vDSO will break userspace programs relying on the kuser helpers.
* We really need a 32-bit compiler this time, and we rely on the user to provide it themselves by setting CROSS_COMPILE_ARM32. Therefore enabling the option by default would make little sense, since the user must explicitly set an environment variable anyway.
CONFIG_COMPAT_VDSO is not directly used in the code, because we want to ignore it (build as if it were not set) if the user didn't set CROSS_COMPILE_ARM32 properly. If the variable has been set to a valid prefix, CONFIG_VDSO32 will be set; this is the option that the code and Makefiles test.
For more flexibility, like CROSS_COMPILE, CROSS_COMPILE_ARM32 can also be set via CONFIG_CROSS_COMPILE_ARM32 (the environment variable overrides the config option).
--- arch/arm64/Kconfig | 26 ++++++++++++++++++++++++++ arch/arm64/Makefile | 28 ++++++++++++++++++++++++++-- arch/arm64/kernel/Makefile | 8 ++++++-- 3 files changed, 58 insertions(+), 4 deletions(-)
arch/arm64/Kconfig +26 -0
@@ -1017,6 +1017,32 @@ config SYSVIPC_COMPAT def_bool y depends on COMPAT && SYSVIPC +config COMPAT_VDSO + bool "32-bit vDSO" + depends on COMPAT + default n + help + Warning: this completely removes the compat vector page, including + kuser helpers, which may break 32-bit processes. + + Warning: a 32-bit toolchain is necessary to build the vDSO. You + must explicitly define which toolchain should be used by setting + CROSS_COMPILE_ARM32 to the prefix of the 32-bit toolchain (same format + as CROSS_COMPILE). If a 32-bit compiler cannot be found, a warning + will be printed and the kernel will be built as if COMPAT_VDSO had not + been set. + + Provide a vDSO to 32-bit processes. It includes the symbols provided + by the vDSO from the 32-bit kernel, so that a 32-bit libc can use + the compat vDSO without modification. It also provides sigreturn + trampolines, and replaces the vector page. + +config CROSS_COMPILE_ARM32 + string "32-bit toolchain prefix" + help + Same as setting CROSS_COMPILE_ARM32 in the environment, but saved for + future builds. The environment variable overrides this config option. + endmenu menu "Power management options"
arch/arm64/Makefile +26 -2
@@ -37,10 +37,32 @@ $(warning LSE atomics not supported by binutils) endif endif -KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) +ifeq ($(CONFIG_COMPAT_VDSO), y) + CROSS_COMPILE_ARM32 ?= $(CONFIG_CROSS_COMPILE_ARM32:"%"=%) + + # Check that the user has provided a valid prefix for the 32-bit toolchain. + # To prevent selecting the system gcc by default, the prefix is not allowed to + # be empty, unlike CROSS_COMPILE. In the unlikely event that the system gcc + # is actually the 32-bit ARM compiler to be used, the variable can be set to + # the dirname (e.g. CROSS_COMPILE_ARM32=/usr/bin/). + # Note: this Makefile is read both before and after regenerating the + # config (if needed). Any warning appearing before the config has been + # regenerated should be ignored. + ifeq ($(CROSS_COMPILE_ARM32),) + $(warning CROSS_COMPILE_ARM32 not defined or empty, the compat vDSO will not be built) + else ifeq ($(shell which $(CROSS_COMPILE_ARM32)gcc 2> /dev/null),) + $(warning $(CROSS_COMPILE_ARM32)gcc not found, the compat vDSO will not be built) + else + export CROSS_COMPILE_ARM32 + export CONFIG_VDSO32 := y + vdso32 := -DCONFIG_VDSO32=1 + endif +endif + +KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(vdso32) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads) -KBUILD_AFLAGS += $(lseinstr) +KBUILD_AFLAGS += $(lseinstr) $(vdso32) ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) KBUILD_CPPFLAGS += -mbig-endian
@@ -139,6 +161,8 @@ archclean: prepare: vdso_prepare vdso_prepare: prepare0 $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso include/generated/vdso-offsets.h + $(if $(CONFIG_VDSO32),$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 \ + include/generated/vdso32-offsets.h) define archhelp echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
arch/arm64/kernel/Makefile +6 -2
@@ -27,8 +27,11 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_ $(obj)/%.stub.o: $(obj)/%.o FORCE $(call if_changed,objcopy) -arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ - sys_compat.o entry32.o +arm64-obj-$(CONFIG_COMPAT) += sys32.o signal32.o sys_compat.o \ + entry32.o +ifneq ($(CONFIG_VDSO32),y) +arm64-obj-y += kuser32.o +endif arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
@@ -52,6 +55,7 @@ arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ cpu-reset.o obj-y += $(arm64-obj-y) vdso/ probes/ +obj-$(CONFIG_VDSO32) += vdso32/ obj-m += $(arm64-obj-m) head-y := head.o extra-y += $(head-y) vmlinux.lds
Signature · 1 line
2.10.0
Catalin Marinas
maintainerRFC PATCH v2 8/8 arm64: Wire up and expose the new compat vDSO
Quoted 4 lines · Kevin Brodsky
* The vDSO page replaces the vector page. The vDSO provides its own sigreturn trampolines, replacing those in the vector page, but the kuser helpers are gone. As a result enabling the compat vDSO will break userspace programs relying on the kuser helpers.
I think vDSO and vectors page should not exclude each other. If you want to disable the vectors page, let's make it an independent config option like the KUSER_HELPERS in arch/arm64/mm/Kconfig. But I would very much like to be able to have both the vDSO and the vectors page at the same time.
Signature · 1 line
Catalin
RFC PATCH v2 8/8 arm64: Wire up and expose the new compat vDSO
Quoted 10 lines · Catalin Marinas
Quoted 4 lines · Kevin Brodsky
* The vDSO page replaces the vector page. The vDSO provides its own sigreturn trampolines, replacing those in the vector page, but the kuser helpers are gone. As a result enabling the compat vDSO will break userspace programs relying on the kuser helpers.
I think vDSO and vectors page should not exclude each other. If you want to disable the vectors page, let's make it an independent config option like the
KUSER_HELPERSinarch/arm64/mm/Kconfig. But I would very much like to be able to have both the vDSO and the vectors page at the same time.
Indeed, I've had exactly the same feedback from Google yesterday (apparently many Android apps with native libs still target ARMv6....). I'll add the option to keep the kuser helpers.
There's a small problem though: how to ensure that the kuser helpers + sigreturn trampolines are always included if the compat vDSO is not built? I can enforce CONFIG_KUSER_HELPERS if !CONFIG_VDSO32 (directly in the code/Makefiles), but the dependency cannot be expressed in Kconfig.
Thanks,
Kevin
Catalin Marinas
maintainerRFC PATCH v2 8/8 arm64: Wire up and expose the new compat vDSO
Quoted 12 lines · Kevin Brodsky
Quoted 10 lines · Catalin Marinas
Quoted 4 lines · Kevin Brodsky
* The vDSO page replaces the vector page. The vDSO provides its own sigreturn trampolines, replacing those in the vector page, but the kuser helpers are gone. As a result enabling the compat vDSO will break userspace programs relying on the kuser helpers.
I think vDSO and vectors page should not exclude each other. If you want to disable the vectors page, let's make it an independent config option like the
KUSER_HELPERSinarch/arm64/mm/Kconfig. But I would very much like to be able to have both the vDSO and the vectors page at the same time.
Quoted 8 lines
Indeed, I've had exactly the same feedback from Google yesterday (apparently many Android apps with native libs still target ARMv6....). I'll add the option to keep the kuser helpers.
There's a small problem though: how to ensure that the kuser helpers + sigreturn trampolines are always included if the compat vDSO is not built? I can enforce
CONFIG_KUSER_HELPERSif !CONFIG_VDSO32 (directly in the code/Makefiles), but the dependency cannot be expressed inKconfig.
Or you could insert a separate "sigpage" as arm32 does. This could leave independently of vDSO or vectors page.
Signature · 1 line
Catalin
RFC PATCH v2 8/8 arm64: Wire up and expose the new compat vDSO
Quoted 16 lines · Catalin Marinas
Quoted 15 lines · Kevin Brodsky
Quoted 10 lines · Catalin Marinas
Quoted 4 lines · Kevin Brodsky
* The vDSO page replaces the vector page. The vDSO provides its own sigreturn trampolines, replacing those in the vector page, but the kuser helpers are gone. As a result enabling the compat vDSO will break userspace programs relying on the kuser helpers.
I think vDSO and vectors page should not exclude each other. If you want to disable the vectors page, let's make it an independent config option like the
KUSER_HELPERSinarch/arm64/mm/Kconfig. But I would very much like to be able to have both the vDSO and the vectors page at the same time.Indeed, I've had exactly the same feedback from Google yesterday (apparently many Android apps with native libs still target ARMv6....). I'll add the option to keep the kuser helpers.
Quoted 6 lines
Quoted 4 lines
There's a small problem though: how to ensure that the kuser helpers + sigreturn trampolines are always included if the compat vDSO is not built? I can enforce
CONFIG_KUSER_HELPERSif !CONFIG_VDSO32 (directly in the code/Makefiles), but the dependency cannot be expressed inKconfig.Or you could insert a separate "sigpage" as arm32 does. This could leave independently of vDSO or vectors page.
Yeah I thought about this too. It's a bit more work but probably cleaner and more flexible, that would also allow to disable the kuser helpers independently of the compat vDSO.
Thanks,
Kevin