From nobody Wed Sep 10 02:37:28 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C70DEB64DC for ; Tue, 11 Jul 2023 13:08:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232814AbjGKNIu (ORCPT ); Tue, 11 Jul 2023 09:08:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38448 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232798AbjGKNIr (ORCPT ); Tue, 11 Jul 2023 09:08:47 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 60FE4E4F for ; Tue, 11 Jul 2023 06:08:45 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id EC765614CD for ; Tue, 11 Jul 2023 13:08:44 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F8BAC433C8; Tue, 11 Jul 2023 13:08:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689080924; bh=QNUVKJXnoZSUVP2Eq6Ceyt+qtwl6KbgMvYZ6bIQgM18=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C04HhYVc8+putRViF/blzDQorcqlJp+TzjaE8DP3/7WfNIsss1zpO4ZzPcaxzK/ES +pMNCbzp8A1+JLlJJEGzXyYo5tnBmtQsDEAjSYWwU14ELLL15eS8NQw+/SgzFz0aKP 5R2M01ThIBXh2jnUQaBGHmFS8tnsS9kfM94fK0iAy2F6H/IPTr6pGJxgOoxSzpQosd MJnDcqvxKNo1Dj5ZzkUJkubVYqkN6Bil381ee+L9D4HqQnYC/mV8G+UNIGWQZmJWrx iGbrc89PzwQY2Dq0uI5lSg77b1+B6aHnM9z1tANEQF/MjHrhbC85d3Q7F1k1G0NZV3 c7MaXU1umlJyA== From: Greg Ungerer To: linux-riscv@lists.infradead.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: palmer@dabbelt.com, viro@zeniv.linux.org.uk, ebiederm@xmission.com, keescook@chromium.org, brauner@kernel.org, Greg Ungerer Subject: [PATCH v2 1/2] binfmt_elf_fdpic: support 64-bit systems Date: Tue, 11 Jul 2023 23:07:53 +1000 Message-Id: <20230711130754.481209-2-gerg@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230711130754.481209-1-gerg@kernel.org> References: <20230711130754.481209-1-gerg@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The binfmt_flat_fdpic code has a number of 32-bit specific data structures associated with it. Extend it to be able to support and be used on 64-bit systems as well. The new code defines a number of key 64-bit variants of the core elf-fdpic data structures - along side the existing 32-bit sized ones. A common set of generic named structures are defined to be either the 32-bit or 64-bit ones as required at compile time. This is a similar technique to that used in the ELF binfmt loader. For example: elf_fdpic_loadseg is either elf32_fdpic_loadseg or elf64_fdpic_loadseg elf_fdpic_loadmap is either elf32_fdpic_loadmap or elf64_fdpic_loadmap the choice based on ELFCLASS32 or ELFCLASS64. Signed-off-by: Greg Ungerer Acked-by: Kees Cook --- v1->v2: rebase onto linux-6.5-rc1 fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++----------------- include/linux/elf-fdpic.h | 14 ++++++++++++- include/uapi/linux/elf-fdpic.h | 15 ++++++++++++++ 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 1c6c5832af86..43b2a2851ba3 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -138,7 +138,7 @@ static int is_constdisp(struct elfhdr *hdr) static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file) { - struct elf32_phdr *phdr; + struct elf_phdr *phdr; unsigned long size; int retval, loop; loff_t pos =3D params->hdr.e_phoff; @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm = *bprm, sp &=3D ~7UL; =20 /* stack the load map(s) */ - len =3D sizeof(struct elf32_fdpic_loadmap); - len +=3D sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs; + len =3D sizeof(struct elf_fdpic_loadmap); + len +=3D sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs; sp =3D (sp - len) & ~7UL; exec_params->map_addr =3D sp; =20 @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm = *bprm, current->mm->context.exec_fdpic_loadmap =3D (unsigned long) sp; =20 if (interp_params->loadmap) { - len =3D sizeof(struct elf32_fdpic_loadmap); - len +=3D sizeof(struct elf32_fdpic_loadseg) * + len =3D sizeof(struct elf_fdpic_loadmap); + len +=3D sizeof(struct elf_fdpic_loadseg) * interp_params->loadmap->nsegs; sp =3D (sp - len) & ~7UL; interp_params->map_addr =3D sp; @@ -740,13 +740,13 @@ static int elf_fdpic_map_file(struct elf_fdpic_params= *params, struct mm_struct *mm, const char *what) { - struct elf32_fdpic_loadmap *loadmap; + struct elf_fdpic_loadmap *loadmap; #ifdef CONFIG_MMU - struct elf32_fdpic_loadseg *mseg; + struct elf_fdpic_loadseg *mseg; unsigned long load_addr; #endif - struct elf32_fdpic_loadseg *seg; - struct elf32_phdr *phdr; + struct elf_fdpic_loadseg *seg; + struct elf_phdr *phdr; unsigned nloads, tmp; unsigned long stop; int loop, ret; @@ -766,7 +766,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *= params, =20 params->loadmap =3D loadmap; =20 - loadmap->version =3D ELF32_FDPIC_LOADMAP_VERSION; + loadmap->version =3D ELF_FDPIC_LOADMAP_VERSION; loadmap->nsegs =3D nloads; =20 /* map the requested LOADs into the memory space */ @@ -839,8 +839,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *= params, if (phdr->p_vaddr >=3D seg->p_vaddr && phdr->p_vaddr + phdr->p_memsz <=3D seg->p_vaddr + seg->p_memsz) { - Elf32_Dyn __user *dyn; - Elf32_Sword d_tag; + Elf_Dyn __user *dyn; + Elf_Sword d_tag; =20 params->dynamic_addr =3D (phdr->p_vaddr - seg->p_vaddr) + @@ -850,11 +850,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params= *params, * one item, and that the last item is a NULL * entry */ if (phdr->p_memsz =3D=3D 0 || - phdr->p_memsz % sizeof(Elf32_Dyn) !=3D 0) + phdr->p_memsz % sizeof(Elf_Dyn) !=3D 0) goto dynamic_error; =20 - tmp =3D phdr->p_memsz / sizeof(Elf32_Dyn); - dyn =3D (Elf32_Dyn __user *)params->dynamic_addr; + tmp =3D phdr->p_memsz / sizeof(Elf_Dyn); + dyn =3D (Elf_Dyn __user *)params->dynamic_addr; if (get_user(d_tag, &dyn[tmp - 1].d_tag) || d_tag !=3D 0) goto dynamic_error; @@ -923,8 +923,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( struct file *file, struct mm_struct *mm) { - struct elf32_fdpic_loadseg *seg; - struct elf32_phdr *phdr; + struct elf_fdpic_loadseg *seg; + struct elf_phdr *phdr; unsigned long load_addr, base =3D ULONG_MAX, top =3D 0, maddr =3D 0; int loop, ret; =20 @@ -1007,8 +1007,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct e= lf_fdpic_params *params, struct file *file, struct mm_struct *mm) { - struct elf32_fdpic_loadseg *seg; - struct elf32_phdr *phdr; + struct elf_fdpic_loadseg *seg; + struct elf_phdr *phdr; unsigned long load_addr, delta_vaddr; int loop, dvset; =20 diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h index 3bea95a1af53..e533f4513194 100644 --- a/include/linux/elf-fdpic.h +++ b/include/linux/elf-fdpic.h @@ -10,13 +10,25 @@ =20 #include =20 +#if ELF_CLASS =3D=3D ELFCLASS32 +#define Elf_Sword Elf32_Sword +#define elf_fdpic_loadseg elf32_fdpic_loadseg +#define elf_fdpic_loadmap elf32_fdpic_loadmap +#define ELF_FDPIC_LOADMAP_VERSION ELF32_FDPIC_LOADMAP_VERSION +#else +#define Elf_Sword Elf64_Sxword +#define elf_fdpic_loadmap elf64_fdpic_loadmap +#define elf_fdpic_loadseg elf64_fdpic_loadseg +#define ELF_FDPIC_LOADMAP_VERSION ELF64_FDPIC_LOADMAP_VERSION +#endif + /* * binfmt binary parameters structure */ struct elf_fdpic_params { struct elfhdr hdr; /* ref copy of ELF header */ struct elf_phdr *phdrs; /* ref copy of PT_PHDR table */ - struct elf32_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace= */ + struct elf_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace */ unsigned long elfhdr_addr; /* mapped ELF header user address */ unsigned long ph_addr; /* mapped PT_PHDR user address */ unsigned long map_addr; /* mapped loadmap user address */ diff --git a/include/uapi/linux/elf-fdpic.h b/include/uapi/linux/elf-fdpic.h index 4fcc6cfebe18..ec23f0871129 100644 --- a/include/uapi/linux/elf-fdpic.h +++ b/include/uapi/linux/elf-fdpic.h @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap { =20 #define ELF32_FDPIC_LOADMAP_VERSION 0x0000 =20 +/* segment mappings for ELF FDPIC libraries/executables/interpreters */ +struct elf64_fdpic_loadseg { + Elf64_Addr addr; /* core address to which mapped */ + Elf64_Addr p_vaddr; /* VMA recorded in file */ + Elf64_Word p_memsz; /* allocation size recorded in file */ +}; + +struct elf64_fdpic_loadmap { + Elf64_Half version; /* version of these structures, just in case... */ + Elf64_Half nsegs; /* number of segments */ + struct elf64_fdpic_loadseg segs[]; +}; + +#define ELF64_FDPIC_LOADMAP_VERSION 0x0000 + #endif /* _UAPI_LINUX_ELF_FDPIC_H */ --=20 2.25.1 From nobody Wed Sep 10 02:37:28 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 680D8EB64DC for ; Tue, 11 Jul 2023 13:08:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232856AbjGKNIz (ORCPT ); Tue, 11 Jul 2023 09:08:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232752AbjGKNIx (ORCPT ); Tue, 11 Jul 2023 09:08:53 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C24418D for ; Tue, 11 Jul 2023 06:08:52 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B02F2614BD for ; Tue, 11 Jul 2023 13:08:51 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EEFD1C433C8; Tue, 11 Jul 2023 13:08:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689080931; bh=YRG1SatEXSQvibLkPPPJGs1s5S3gHEmvd7gZSzwoAnU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m8vIO/3oz0iV+JgNzmjwzr+CqcICYWIe7Rog2iDkpGmFwZJYExFefwtunqZdT6VMl EQnVR6hgqYxvFUCn1yz1VxthdhaUjLWAQNQknByoD2ylRfeXIGTkinPU7DRPpEARDZ 7wX0sSRV4gsPE+0pjG7tc7lPTroIyaiNr9krJQaOVEEiaUTnd9kPtjM1i7eDyrWveS QtdstMrnsA2dPoXWxPs7dLSeHSQaNy11g5joZAo4bkYF0MURxHjYoP8QJ1BL2CHNxl dRj4mzhN1/YDtHZnmVaI3l9GfljurrccBjsCIrXpFRYcC9/hqYTui5DrmkZ/0JYoKJ JsEwgA/i1IYjg== From: Greg Ungerer To: linux-riscv@lists.infradead.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: palmer@dabbelt.com, viro@zeniv.linux.org.uk, ebiederm@xmission.com, keescook@chromium.org, brauner@kernel.org, Greg Ungerer Subject: [PATCH v2 2/2] riscv: support the elf-fdpic binfmt loader Date: Tue, 11 Jul 2023 23:07:54 +1000 Message-Id: <20230711130754.481209-3-gerg@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230711130754.481209-1-gerg@kernel.org> References: <20230711130754.481209-1-gerg@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 Acked-by: Kees Cook --- v1->v2: rebase onto linux-6.5-rc1 increment PTRACE_GETFDPIC value to keep it unique arch/riscv/include/asm/elf.h | 11 ++++++++++- arch/riscv/include/asm/mmu.h | 4 ++++ arch/riscv/include/uapi/asm/ptrace.h | 5 +++++ fs/Kconfig.binfmt | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index c24280774caf..c33fe923ef6d 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h @@ -41,6 +41,7 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr); #define compat_elf_check_arch compat_elf_check_arch =20 #define CORE_DUMP_USE_REGSET +#define ELF_FDPIC_CORE_EFLAGS 0 #define ELF_EXEC_PAGESIZE (PAGE_SIZE) =20 /* @@ -69,6 +70,13 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr); #define ELF_HWCAP riscv_get_elf_hwcap() extern unsigned long elf_hwcap; =20 +#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_= addr) \ + do { \ + (_r)->a1 =3D _exec_map_addr; \ + (_r)->a2 =3D _interp_map_addr; \ + (_r)->a3 =3D dynamic_addr; \ + } while (0) + /* * This yields a string that ld.so will use to load implementation * specific libraries for optimization. This is more specific in @@ -78,7 +86,6 @@ extern unsigned long elf_hwcap; =20 #define COMPAT_ELF_PLATFORM (NULL) =20 -#ifdef CONFIG_MMU #define ARCH_DLINFO \ do { \ /* \ @@ -115,6 +122,8 @@ do { \ else \ NEW_AUX_ENT(AT_IGNORE, 0); \ } while (0) + +#ifdef CONFIG_MMU #define ARCH_HAS_SETUP_ADDITIONAL_PAGES struct linux_binprm; extern int arch_setup_additional_pages(struct linux_binprm *bprm, diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h index 0099dc116168..355504b37f8e 100644 --- a/arch/riscv/include/asm/mmu.h +++ b/arch/riscv/include/asm/mmu.h @@ -20,6 +20,10 @@ typedef struct { /* A local icache flush is needed before user execution can resume. */ cpumask_t icache_stale_mask; #endif +#ifdef CONFIG_BINFMT_ELF_FDPIC + unsigned long exec_fdpic_loadmap; + unsigned long interp_fdpic_loadmap; +#endif } mm_context_t; =20 void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi= /asm/ptrace.h index e17c550986a6..30f6d6537adc 100644 --- a/arch/riscv/include/uapi/asm/ptrace.h +++ b/arch/riscv/include/uapi/asm/ptrace.h @@ -10,6 +10,11 @@ =20 #include =20 +#define PTRACE_GETFDPIC 33 + +#define PTRACE_GETFDPIC_EXEC 0 +#define PTRACE_GETFDPIC_INTERP 1 + /* * User-mode register state for core dumps, ptrace, sigcontext * diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 93539aac0e5b..f5693164ca9a 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -58,7 +58,7 @@ config ARCH_USE_GNU_PROPERTY config BINFMT_ELF_FDPIC bool "Kernel support for FDPIC ELF binaries" default y if !BINFMT_ELF - depends on ARM || ((M68K || SUPERH || XTENSA) && !MMU) + depends on ARM || ((M68K || RISCV || SUPERH || XTENSA) && !MMU) select ELFCORE help ELF FDPIC binaries are based on ELF, but allow the individual load --=20 2.25.1