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

From: Guo Ren
Date: Thu Mar 10 2022 - 05:06:31 EST


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@xxxxxxxxxx> wrote:
>
> From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
>
> Implement necessary type and macro for compat elf. See the code
> comment for detail.
>
> Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
> Signed-off-by: Guo Ren <guoren@xxxxxxxxxx>
> Reviewed-by: Arnd Bergmann <arnd@xxxxxxxx>
> ---
> 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/