riscv: support the elf-fdpic binfmt loader

Add support for enabling and using the binfmt_elf_fdpic program loader
on RISC-V platforms. The most important change is to setup registers
during program load to pass the mapping addresses to the new process.

One of the interesting features of the elf-fdpic loader is that it
also allows appropriately compiled ELF format binaries to be loaded on
nommu systems. Appropriate being those compiled with -pie.

Signed-off-by: Greg Ungerer <gerg@kernel.org>
Acked-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20230711130754.481209-3-gerg@kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Greg Ungerer 2023-07-11 23:07:54 +10:00 committed by Palmer Dabbelt
parent b922bf04d2
commit 9549fb354e
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
4 changed files with 20 additions and 2 deletions

View File

@ -41,6 +41,7 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
#define compat_elf_check_arch compat_elf_check_arch #define compat_elf_check_arch compat_elf_check_arch
#define CORE_DUMP_USE_REGSET #define CORE_DUMP_USE_REGSET
#define ELF_FDPIC_CORE_EFLAGS 0
#define ELF_EXEC_PAGESIZE (PAGE_SIZE) #define ELF_EXEC_PAGESIZE (PAGE_SIZE)
/* /*
@ -69,6 +70,13 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
#define ELF_HWCAP riscv_get_elf_hwcap() #define ELF_HWCAP riscv_get_elf_hwcap()
extern unsigned long elf_hwcap; extern unsigned long elf_hwcap;
#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \
do { \
(_r)->a1 = _exec_map_addr; \
(_r)->a2 = _interp_map_addr; \
(_r)->a3 = dynamic_addr; \
} while (0)
/* /*
* This yields a string that ld.so will use to load implementation * This yields a string that ld.so will use to load implementation
* specific libraries for optimization. This is more specific in * specific libraries for optimization. This is more specific in
@ -78,7 +86,6 @@ extern unsigned long elf_hwcap;
#define COMPAT_ELF_PLATFORM (NULL) #define COMPAT_ELF_PLATFORM (NULL)
#ifdef CONFIG_MMU
#define ARCH_DLINFO \ #define ARCH_DLINFO \
do { \ do { \
/* \ /* \
@ -115,6 +122,8 @@ do { \
else \ else \
NEW_AUX_ENT(AT_IGNORE, 0); \ NEW_AUX_ENT(AT_IGNORE, 0); \
} while (0) } while (0)
#ifdef CONFIG_MMU
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
struct linux_binprm; struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm, extern int arch_setup_additional_pages(struct linux_binprm *bprm,

View File

@ -20,6 +20,10 @@ typedef struct {
/* A local icache flush is needed before user execution can resume. */ /* A local icache flush is needed before user execution can resume. */
cpumask_t icache_stale_mask; cpumask_t icache_stale_mask;
#endif #endif
#ifdef CONFIG_BINFMT_ELF_FDPIC
unsigned long exec_fdpic_loadmap;
unsigned long interp_fdpic_loadmap;
#endif
} mm_context_t; } mm_context_t;
void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa,

View File

@ -10,6 +10,11 @@
#include <linux/types.h> #include <linux/types.h>
#define PTRACE_GETFDPIC 33
#define PTRACE_GETFDPIC_EXEC 0
#define PTRACE_GETFDPIC_INTERP 1
/* /*
* User-mode register state for core dumps, ptrace, sigcontext * User-mode register state for core dumps, ptrace, sigcontext
* *

View File

@ -58,7 +58,7 @@ config ARCH_USE_GNU_PROPERTY
config BINFMT_ELF_FDPIC config BINFMT_ELF_FDPIC
bool "Kernel support for FDPIC ELF binaries" bool "Kernel support for FDPIC ELF binaries"
default y if !BINFMT_ELF default y if !BINFMT_ELF
depends on ARM || ((M68K || SUPERH || XTENSA) && !MMU) depends on ARM || ((M68K || RISCV || SUPERH || XTENSA) && !MMU)
select ELFCORE select ELFCORE
help help
ELF FDPIC binaries are based on ELF, but allow the individual load ELF FDPIC binaries are based on ELF, but allow the individual load