[PATCH V7 14/20] riscv: compat: Add elf.h implementation

Guo Ren guoren at kernel.org
Thu Mar 10 02:06:10 PST 2022


Hi Palmer & Arnd

Seems we need a more strict check to distinguish ELFCLASS32/64 RISC in
elf for the elf_check_arch & compat_elf_check_arch. SET_PERSONALITY is
not enough.

diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index d87d3bcc758d..2fcd854fb516 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -33,7 +33,8 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ((x)->e_machine == EM_RISCV)
+#define elf_check_arch(x) (((x)->e_machine == EM_RISCV) && \
+                          ((x)->e_ident[EI_CLASS] == ELF_CLASS))

 /*
  * Use the same code with elf_check_arch, because elf32_hdr &
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 8caa5f48d0a1..f46016e96235 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -88,7 +88,9 @@ static bool compat_mode_supported __read_mostly;

 bool compat_elf_check_arch(Elf32_Ehdr *hdr)
 {
-       return compat_mode_supported && hdr->e_machine == EM_RISCV;
+       return compat_mode_supported &&
+              hdr->e_machine == EM_RISCV &&
+              hdr->e_ident[EI_CLASS] == ELFCLASS32;
 }

 static int __init compat_mode_detect(void)

On Mon, Feb 28, 2022 at 12:30 AM <guoren at kernel.org> wrote:
>
> From: Guo Ren <guoren at linux.alibaba.com>
>
> Implement necessary type and macro for compat elf. See the code
> comment for detail.
>
> Signed-off-by: Guo Ren <guoren at linux.alibaba.com>
> Signed-off-by: Guo Ren <guoren at kernel.org>
> Reviewed-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  arch/riscv/include/asm/elf.h | 46 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
> index f53c40026c7a..aee40040917b 100644
> --- a/arch/riscv/include/asm/elf.h
> +++ b/arch/riscv/include/asm/elf.h
> @@ -8,6 +8,8 @@
>  #ifndef _ASM_RISCV_ELF_H
>  #define _ASM_RISCV_ELF_H
>
> +#include <uapi/linux/elf.h>
> +#include <linux/compat.h>
>  #include <uapi/asm/elf.h>
>  #include <asm/auxvec.h>
>  #include <asm/byteorder.h>
> @@ -18,11 +20,13 @@
>   */
>  #define ELF_ARCH       EM_RISCV
>
> +#ifndef ELF_CLASS
>  #ifdef CONFIG_64BIT
>  #define ELF_CLASS      ELFCLASS64
>  #else
>  #define ELF_CLASS      ELFCLASS32
>  #endif
> +#endif
>
>  #define ELF_DATA       ELFDATA2LSB
>
> @@ -31,6 +35,13 @@
>   */
>  #define elf_check_arch(x) ((x)->e_machine == EM_RISCV)
>
> +/*
> + * Use the same code with elf_check_arch, because elf32_hdr &
> + * elf64_hdr e_machine's offset are different. The checker is
> + * a little bit simple compare to other architectures.
> + */
> +#define compat_elf_check_arch(x) ((x)->e_machine == EM_RISCV)
> +
>  #define CORE_DUMP_USE_REGSET
>  #define ELF_EXEC_PAGESIZE      (PAGE_SIZE)
>
> @@ -43,8 +54,14 @@
>  #define ELF_ET_DYN_BASE                ((TASK_SIZE / 3) * 2)
>
>  #ifdef CONFIG_64BIT
> +#ifdef CONFIG_COMPAT
> +#define STACK_RND_MASK         (test_thread_flag(TIF_32BIT) ? \
> +                                0x7ff >> (PAGE_SHIFT - 12) : \
> +                                0x3ffff >> (PAGE_SHIFT - 12))
> +#else
>  #define STACK_RND_MASK         (0x3ffff >> (PAGE_SHIFT - 12))
>  #endif
> +#endif
>  /*
>   * This yields a mask that user programs can use to figure out what
>   * instruction set this CPU supports.  This could be done in user space,
> @@ -60,11 +77,19 @@ extern unsigned long elf_hwcap;
>   */
>  #define ELF_PLATFORM   (NULL)
>
> +#define COMPAT_ELF_PLATFORM    (NULL)
> +
>  #ifdef CONFIG_MMU
>  #define ARCH_DLINFO                                            \
>  do {                                                           \
> +       /*                                                      \
> +        * Note that we add ulong after elf_addr_t because      \
> +        * casting current->mm->context.vdso triggers a cast    \
> +        * warning of cast from pointer to integer for          \
> +        * COMPAT ELFCLASS32.                                   \
> +        */                                                     \
>         NEW_AUX_ENT(AT_SYSINFO_EHDR,                            \
> -               (elf_addr_t)current->mm->context.vdso);         \
> +               (elf_addr_t)(ulong)current->mm->context.vdso);  \
>         NEW_AUX_ENT(AT_L1I_CACHESIZE,                           \
>                 get_cache_size(1, CACHE_TYPE_INST));            \
>         NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY,                       \
> @@ -90,4 +115,23 @@ do {                                                        \
>                 *(struct user_regs_struct *)regs;       \
>  } while (0);
>
> +#ifdef CONFIG_COMPAT
> +
> +#define SET_PERSONALITY(ex)                                    \
> +do {    if ((ex).e_ident[EI_CLASS] == ELFCLASS32)              \
> +               set_thread_flag(TIF_32BIT);                     \
> +       else                                                    \
> +               clear_thread_flag(TIF_32BIT);                   \
> +       if (personality(current->personality) != PER_LINUX32)   \
> +               set_personality(PER_LINUX |                     \
> +                       (current->personality & (~PER_MASK)));  \
> +} while (0)
> +
> +#define COMPAT_ELF_ET_DYN_BASE         ((TASK_SIZE_32 / 3) * 2)
> +
> +/* rv32 registers */
> +typedef compat_ulong_t                 compat_elf_greg_t;
> +typedef compat_elf_greg_t              compat_elf_gregset_t[ELF_NGREG];
> +
> +#endif /* CONFIG_COMPAT */
>  #endif /* _ASM_RISCV_ELF_H */
> --
> 2.25.1
>


-- 
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/



More information about the linux-riscv mailing list