[PATCH 2/6] arm64: compat: Allow 32-bit vdso and sigpage to co-exist

Vincenzo Frascino vincenzo.frascino at arm.com
Tue Jun 23 07:53:08 EDT 2020



On 6/23/20 9:54 AM, Will Deacon wrote:
> In preparation for removing the signal trampoline from the compat vDSO,
> allow the sigpage and the compat vDSO to co-exist.
> 
> Signed-off-by: Will Deacon <will at kernel.org>

Reviewed-by: Vincenzo Frascino <vincenzo.frascino at arm.com>

> ---
>  arch/arm64/include/asm/mmu.h |  3 ++
>  arch/arm64/kernel/Makefile   |  2 --
>  arch/arm64/kernel/signal32.c |  2 +-
>  arch/arm64/kernel/vdso.c     | 61 +++++++++++++++++-------------------
>  4 files changed, 32 insertions(+), 36 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> index 68140fdd89d6..8444df000181 100644
> --- a/arch/arm64/include/asm/mmu.h
> +++ b/arch/arm64/include/asm/mmu.h
> @@ -19,6 +19,9 @@
>  
>  typedef struct {
>  	atomic64_t	id;
> +#ifdef CONFIG_COMPAT
> +	void		*sigpage;
> +#endif
>  	void		*vdso;
>  	unsigned long	flags;
>  } mm_context_t;
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 151f28521f1e..a561cbb91d4d 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -29,9 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
>  
>  obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
>  					   sys_compat.o
> -ifneq ($(CONFIG_COMPAT_VDSO), y)
>  obj-$(CONFIG_COMPAT)			+= sigreturn32.o
> -endif
>  obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
>  obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o entry-ftrace.o
>  obj-$(CONFIG_MODULES)			+= module.o
> diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
> index 82feca6f7052..0aa0b33744de 100644
> --- a/arch/arm64/kernel/signal32.c
> +++ b/arch/arm64/kernel/signal32.c
> @@ -371,7 +371,7 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
>  		if (ka->sa.sa_flags & SA_SIGINFO)
>  			idx += 3;
>  
> -		retcode = (unsigned long)current->mm->context.vdso +
> +		retcode = (unsigned long)current->mm->context.sigpage +
>  			  (idx << 2) + thumb;
>  #endif
>  	}
> diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
> index 4e016574bd91..e546df0efefb 100644
> --- a/arch/arm64/kernel/vdso.c
> +++ b/arch/arm64/kernel/vdso.c
> @@ -191,15 +191,12 @@ enum aarch32_map {
>  #ifdef CONFIG_COMPAT_VDSO
>  	AA32_MAP_VVAR,
>  	AA32_MAP_VDSO,
> -#else
> -	AA32_MAP_SIGPAGE
>  #endif
> +	AA32_MAP_SIGPAGE
>  };
>  
>  static struct page *aarch32_vectors_page __ro_after_init;
> -#ifndef CONFIG_COMPAT_VDSO
>  static struct page *aarch32_sig_page __ro_after_init;
> -#endif
>  
>  static struct vm_special_mapping aarch32_vdso_maps[] = {
>  	[AA32_MAP_VECTORS] = {
> @@ -214,12 +211,11 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
>  		.name = "[vdso]",
>  		.mremap = aarch32_vdso_mremap,
>  	},
> -#else
> +#endif /* CONFIG_COMPAT_VDSO */
>  	[AA32_MAP_SIGPAGE] = {
>  		.name	= "[sigpage]", /* ABI */
>  		.pages	= &aarch32_sig_page,
>  	},
> -#endif /* CONFIG_COMPAT_VDSO */
>  };
>  
>  static int aarch32_alloc_kuser_vdso_page(void)
> @@ -242,27 +238,11 @@ static int aarch32_alloc_kuser_vdso_page(void)
>  	return 0;
>  }
>  
> -#ifdef CONFIG_COMPAT_VDSO
> -static int __aarch32_alloc_vdso_pages(void)
> -{
> -	int ret;
> -
> -	vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
> -	vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
> -
> -	ret = __vdso_init(VDSO_ABI_AA32);
> -	if (ret)
> -		return ret;
> -
> -	return aarch32_alloc_kuser_vdso_page();
> -}
> -#else
> -static int __aarch32_alloc_vdso_pages(void)
> +static int aarch32_alloc_sigpage(void)
>  {
>  	extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[];
>  	int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start;
>  	unsigned long sigpage;
> -	int ret;
>  
>  	sigpage = get_zeroed_page(GFP_ATOMIC);
>  	if (!sigpage)
> @@ -271,18 +251,34 @@ static int __aarch32_alloc_vdso_pages(void)
>  	memcpy((void *)sigpage, __aarch32_sigret_code_start, sigret_sz);
>  	aarch32_sig_page = virt_to_page(sigpage);
>  	flush_dcache_page(aarch32_sig_page);
> +	return 0;
> +}
>  
> -	ret = aarch32_alloc_kuser_vdso_page();
> -	if (ret)
> -		free_page(sigpage);
> +#ifdef CONFIG_COMPAT_VDSO
> +static int __aarch32_alloc_vdso_pages(void)
> +{
> +	vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
> +	vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
>  
> -	return ret;
> +	return __vdso_init(VDSO_ABI_AA32);
>  }
>  #endif /* CONFIG_COMPAT_VDSO */
>  
>  static int __init aarch32_alloc_vdso_pages(void)
>  {
> -	return __aarch32_alloc_vdso_pages();
> +	int ret;
> +
> +#ifdef CONFIG_COMPAT_VDSO
> +	ret = __aarch32_alloc_vdso_pages();
> +	if (ret)
> +		return ret;
> +#endif
> +
> +	ret = aarch32_alloc_sigpage();
> +	if (ret)
> +		return ret;
> +
> +	return aarch32_alloc_kuser_vdso_page();
>  }
>  arch_initcall(aarch32_alloc_vdso_pages);
>  
> @@ -305,7 +301,6 @@ static int aarch32_kuser_helpers_setup(struct mm_struct *mm)
>  	return PTR_ERR_OR_ZERO(ret);
>  }
>  
> -#ifndef CONFIG_COMPAT_VDSO
>  static int aarch32_sigreturn_setup(struct mm_struct *mm)
>  {
>  	unsigned long addr;
> @@ -328,12 +323,11 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm)
>  	if (IS_ERR(ret))
>  		goto out;
>  
> -	mm->context.vdso = (void *)addr;
> +	mm->context.sigpage = (void *)addr;
>  
>  out:
>  	return PTR_ERR_OR_ZERO(ret);
>  }
> -#endif /* !CONFIG_COMPAT_VDSO */
>  
>  int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
>  {
> @@ -352,10 +346,11 @@ int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
>  				       mm,
>  				       bprm,
>  				       uses_interp);
> -#else
> -	ret = aarch32_sigreturn_setup(mm);
> +	if (ret)
> +		goto out;
>  #endif /* CONFIG_COMPAT_VDSO */
>  
> +	ret = aarch32_sigreturn_setup(mm);
>  out:
>  	mmap_write_unlock(mm);
>  	return ret;
> 

-- 
Regards,
Vincenzo



More information about the linux-arm-kernel mailing list