Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

binfmt_elf_fdpic: support 64-bit systems

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 <gerg@kernel.org>
Acked-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20230711130754.481209-2-gerg@kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>

authored by

Greg Ungerer and committed by
Palmer Dabbelt
b922bf04 06c2afb8

+47 -20
+19 -19
fs/binfmt_elf_fdpic.c
··· 138 138 static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, 139 139 struct file *file) 140 140 { 141 - struct elf32_phdr *phdr; 141 + struct elf_phdr *phdr; 142 142 unsigned long size; 143 143 int retval, loop; 144 144 loff_t pos = params->hdr.e_phoff; ··· 560 560 sp &= ~7UL; 561 561 562 562 /* stack the load map(s) */ 563 - len = sizeof(struct elf32_fdpic_loadmap); 564 - len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs; 563 + len = sizeof(struct elf_fdpic_loadmap); 564 + len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs; 565 565 sp = (sp - len) & ~7UL; 566 566 exec_params->map_addr = sp; 567 567 ··· 571 571 current->mm->context.exec_fdpic_loadmap = (unsigned long) sp; 572 572 573 573 if (interp_params->loadmap) { 574 - len = sizeof(struct elf32_fdpic_loadmap); 575 - len += sizeof(struct elf32_fdpic_loadseg) * 574 + len = sizeof(struct elf_fdpic_loadmap); 575 + len += sizeof(struct elf_fdpic_loadseg) * 576 576 interp_params->loadmap->nsegs; 577 577 sp = (sp - len) & ~7UL; 578 578 interp_params->map_addr = sp; ··· 740 740 struct mm_struct *mm, 741 741 const char *what) 742 742 { 743 - struct elf32_fdpic_loadmap *loadmap; 743 + struct elf_fdpic_loadmap *loadmap; 744 744 #ifdef CONFIG_MMU 745 - struct elf32_fdpic_loadseg *mseg; 745 + struct elf_fdpic_loadseg *mseg; 746 746 unsigned long load_addr; 747 747 #endif 748 - struct elf32_fdpic_loadseg *seg; 749 - struct elf32_phdr *phdr; 748 + struct elf_fdpic_loadseg *seg; 749 + struct elf_phdr *phdr; 750 750 unsigned nloads, tmp; 751 751 unsigned long stop; 752 752 int loop, ret; ··· 766 766 767 767 params->loadmap = loadmap; 768 768 769 - loadmap->version = ELF32_FDPIC_LOADMAP_VERSION; 769 + loadmap->version = ELF_FDPIC_LOADMAP_VERSION; 770 770 loadmap->nsegs = nloads; 771 771 772 772 /* map the requested LOADs into the memory space */ ··· 839 839 if (phdr->p_vaddr >= seg->p_vaddr && 840 840 phdr->p_vaddr + phdr->p_memsz <= 841 841 seg->p_vaddr + seg->p_memsz) { 842 - Elf32_Dyn __user *dyn; 843 - Elf32_Sword d_tag; 842 + Elf_Dyn __user *dyn; 843 + Elf_Sword d_tag; 844 844 845 845 params->dynamic_addr = 846 846 (phdr->p_vaddr - seg->p_vaddr) + ··· 850 850 * one item, and that the last item is a NULL 851 851 * entry */ 852 852 if (phdr->p_memsz == 0 || 853 - phdr->p_memsz % sizeof(Elf32_Dyn) != 0) 853 + phdr->p_memsz % sizeof(Elf_Dyn) != 0) 854 854 goto dynamic_error; 855 855 856 - tmp = phdr->p_memsz / sizeof(Elf32_Dyn); 857 - dyn = (Elf32_Dyn __user *)params->dynamic_addr; 856 + tmp = phdr->p_memsz / sizeof(Elf_Dyn); 857 + dyn = (Elf_Dyn __user *)params->dynamic_addr; 858 858 if (get_user(d_tag, &dyn[tmp - 1].d_tag) || 859 859 d_tag != 0) 860 860 goto dynamic_error; ··· 923 923 struct file *file, 924 924 struct mm_struct *mm) 925 925 { 926 - struct elf32_fdpic_loadseg *seg; 927 - struct elf32_phdr *phdr; 926 + struct elf_fdpic_loadseg *seg; 927 + struct elf_phdr *phdr; 928 928 unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0; 929 929 int loop, ret; 930 930 ··· 1007 1007 struct file *file, 1008 1008 struct mm_struct *mm) 1009 1009 { 1010 - struct elf32_fdpic_loadseg *seg; 1011 - struct elf32_phdr *phdr; 1010 + struct elf_fdpic_loadseg *seg; 1011 + struct elf_phdr *phdr; 1012 1012 unsigned long load_addr, delta_vaddr; 1013 1013 int loop, dvset; 1014 1014
+13 -1
include/linux/elf-fdpic.h
··· 10 10 11 11 #include <uapi/linux/elf-fdpic.h> 12 12 13 + #if ELF_CLASS == ELFCLASS32 14 + #define Elf_Sword Elf32_Sword 15 + #define elf_fdpic_loadseg elf32_fdpic_loadseg 16 + #define elf_fdpic_loadmap elf32_fdpic_loadmap 17 + #define ELF_FDPIC_LOADMAP_VERSION ELF32_FDPIC_LOADMAP_VERSION 18 + #else 19 + #define Elf_Sword Elf64_Sxword 20 + #define elf_fdpic_loadmap elf64_fdpic_loadmap 21 + #define elf_fdpic_loadseg elf64_fdpic_loadseg 22 + #define ELF_FDPIC_LOADMAP_VERSION ELF64_FDPIC_LOADMAP_VERSION 23 + #endif 24 + 13 25 /* 14 26 * binfmt binary parameters structure 15 27 */ 16 28 struct elf_fdpic_params { 17 29 struct elfhdr hdr; /* ref copy of ELF header */ 18 30 struct elf_phdr *phdrs; /* ref copy of PT_PHDR table */ 19 - struct elf32_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace */ 31 + struct elf_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace */ 20 32 unsigned long elfhdr_addr; /* mapped ELF header user address */ 21 33 unsigned long ph_addr; /* mapped PT_PHDR user address */ 22 34 unsigned long map_addr; /* mapped loadmap user address */
+15
include/uapi/linux/elf-fdpic.h
··· 32 32 33 33 #define ELF32_FDPIC_LOADMAP_VERSION 0x0000 34 34 35 + /* segment mappings for ELF FDPIC libraries/executables/interpreters */ 36 + struct elf64_fdpic_loadseg { 37 + Elf64_Addr addr; /* core address to which mapped */ 38 + Elf64_Addr p_vaddr; /* VMA recorded in file */ 39 + Elf64_Word p_memsz; /* allocation size recorded in file */ 40 + }; 41 + 42 + struct elf64_fdpic_loadmap { 43 + Elf64_Half version; /* version of these structures, just in case... */ 44 + Elf64_Half nsegs; /* number of segments */ 45 + struct elf64_fdpic_loadseg segs[]; 46 + }; 47 + 48 + #define ELF64_FDPIC_LOADMAP_VERSION 0x0000 49 + 35 50 #endif /* _UAPI_LINUX_ELF_FDPIC_H */