On some architectures, modules (and the kernel itself) may have different ELF properties than native userspace executables. On arm64 hybrid PCuABI kernels, userspace executables have the purecap EF_AARCH64_CHERI_PURECAP ELF flag, while modules do not. This means that elf_check_arch() cannot be used for modules.
For the time being, work around this by skipping elf_check_arch() for modules when CONFIG_CHERI_PURECAP_UABI=y, and do the entire ELF check in module_elf_check_arch(). This enables modules to be loaded on a PCuABI kernel.
Signed-off-by: Kristina Martsenko kristina.martsenko@arm.com --- Changes in v2: - Use ARCH_MODULE_SKIP_ELF_CHECK to work around changes in the 6.4 kernel - v1: https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org/...
arch/arm64/include/asm/elf.h | 9 +-------- arch/arm64/kernel/module.c | 8 ++++++++ kernel/module/main.c | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 6189c8614dd6..f01f1f99cf03 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -95,16 +95,9 @@ * This is used to ensure we don't load something for the wrong architecture. */ #ifdef CONFIG_CHERI_PURECAP_UABI -/* - * TODO [PCuABI] - elf_check_arch() is also used by the kernel module loader to - * verify the ELF headers. However, kernel modules, just like the kernel, are - * currently hybrid binaries and therefore do not have the - * EF_AARCH64_CHERI_PURECAP flag. As a result elf_check_arch() currently fails - * for kernel modules. This could be solved by introducing a new macro to check - * kernel modules. - */ #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64 && \ (x)->e_flags & EF_AARCH64_CHERI_PURECAP) +#define ARCH_MODULE_SKIP_ELF_CHECK #else #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) #endif diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 5af4975caeb5..46f5f161fc0a 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -22,6 +22,14 @@ #include <asm/scs.h> #include <asm/sections.h>
+#ifdef CONFIG_CHERI_PURECAP_UABI +bool module_elf_check_arch(Elf_Ehdr *hdr) +{ + return hdr->e_machine == EM_AARCH64 && + !(hdr->e_flags & EF_AARCH64_CHERI_PURECAP); +} +#endif + void *module_alloc(unsigned long size) { u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; diff --git a/kernel/module/main.c b/kernel/module/main.c index 4e2cf784cf8c..076ba5f21ac9 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1688,11 +1688,13 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) info->hdr->e_type, ET_REL); goto no_exec; } +#ifndef ARCH_MODULE_SKIP_ELF_CHECK if (!elf_check_arch(info->hdr)) { pr_err("Invalid architecture in ELF header: %u\n", info->hdr->e_machine); goto no_exec; } +#endif if (!module_elf_check_arch(info->hdr)) { pr_err("Invalid module architecture in ELF header: %u\n", info->hdr->e_machine);
On 29/06/2023 16:07, Kristina Martsenko wrote:
On some architectures, modules (and the kernel itself) may have different ELF properties than native userspace executables. On arm64 hybrid PCuABI kernels, userspace executables have the purecap EF_AARCH64_CHERI_PURECAP ELF flag, while modules do not. This means that elf_check_arch() cannot be used for modules.
For the time being, work around this by skipping elf_check_arch() for modules when CONFIG_CHERI_PURECAP_UABI=y, and do the entire ELF check in module_elf_check_arch(). This enables modules to be loaded on a PCuABI kernel.
Signed-off-by: Kristina Martsenko kristina.martsenko@arm.com
Changes in v2:
- Use ARCH_MODULE_SKIP_ELF_CHECK to work around changes in the 6.4 kernel
Thanks for that reworked patch! Looks good and the kselftests pass on the board + FVP. I've now added it to my 6.4-based branch.
Kevin
arch/arm64/include/asm/elf.h | 9 +-------- arch/arm64/kernel/module.c | 8 ++++++++ kernel/module/main.c | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 6189c8614dd6..f01f1f99cf03 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -95,16 +95,9 @@
- This is used to ensure we don't load something for the wrong architecture.
*/ #ifdef CONFIG_CHERI_PURECAP_UABI -/*
- TODO [PCuABI] - elf_check_arch() is also used by the kernel module loader to
- verify the ELF headers. However, kernel modules, just like the kernel, are
- currently hybrid binaries and therefore do not have the
- EF_AARCH64_CHERI_PURECAP flag. As a result elf_check_arch() currently fails
- for kernel modules. This could be solved by introducing a new macro to check
- kernel modules.
- */
#define elf_check_arch(x) ((x)->e_machine == EM_AARCH64 && \ (x)->e_flags & EF_AARCH64_CHERI_PURECAP) +#define ARCH_MODULE_SKIP_ELF_CHECK #else #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) #endif diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 5af4975caeb5..46f5f161fc0a 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -22,6 +22,14 @@ #include <asm/scs.h> #include <asm/sections.h> +#ifdef CONFIG_CHERI_PURECAP_UABI +bool module_elf_check_arch(Elf_Ehdr *hdr) +{
- return hdr->e_machine == EM_AARCH64 &&
!(hdr->e_flags & EF_AARCH64_CHERI_PURECAP);
+} +#endif
void *module_alloc(unsigned long size) { u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; diff --git a/kernel/module/main.c b/kernel/module/main.c index 4e2cf784cf8c..076ba5f21ac9 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1688,11 +1688,13 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) info->hdr->e_type, ET_REL); goto no_exec; } +#ifndef ARCH_MODULE_SKIP_ELF_CHECK if (!elf_check_arch(info->hdr)) { pr_err("Invalid architecture in ELF header: %u\n", info->hdr->e_machine); goto no_exec; } +#endif if (!module_elf_check_arch(info->hdr)) { pr_err("Invalid module architecture in ELF header: %u\n", info->hdr->e_machine);
linux-morello@op-lists.linaro.org