Skip to content

Commit b922bf0

Browse files
Greg Ungererpalmer-dabbelt
authored andcommitted
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>
1 parent 06c2afb commit b922bf0

File tree

3 files changed

+47
-20
lines changed

3 files changed

+47
-20
lines changed

fs/binfmt_elf_fdpic.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static int is_constdisp(struct elfhdr *hdr)
138138
static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
139139
struct file *file)
140140
{
141-
struct elf32_phdr *phdr;
141+
struct elf_phdr *phdr;
142142
unsigned long size;
143143
int retval, loop;
144144
loff_t pos = params->hdr.e_phoff;
@@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
560560
sp &= ~7UL;
561561

562562
/* 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;
565565
sp = (sp - len) & ~7UL;
566566
exec_params->map_addr = sp;
567567

@@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
571571
current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
572572

573573
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) *
576576
interp_params->loadmap->nsegs;
577577
sp = (sp - len) & ~7UL;
578578
interp_params->map_addr = sp;
@@ -740,13 +740,13 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
740740
struct mm_struct *mm,
741741
const char *what)
742742
{
743-
struct elf32_fdpic_loadmap *loadmap;
743+
struct elf_fdpic_loadmap *loadmap;
744744
#ifdef CONFIG_MMU
745-
struct elf32_fdpic_loadseg *mseg;
745+
struct elf_fdpic_loadseg *mseg;
746746
unsigned long load_addr;
747747
#endif
748-
struct elf32_fdpic_loadseg *seg;
749-
struct elf32_phdr *phdr;
748+
struct elf_fdpic_loadseg *seg;
749+
struct elf_phdr *phdr;
750750
unsigned nloads, tmp;
751751
unsigned long stop;
752752
int loop, ret;
@@ -766,7 +766,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
766766

767767
params->loadmap = loadmap;
768768

769-
loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
769+
loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
770770
loadmap->nsegs = nloads;
771771

772772
/* map the requested LOADs into the memory space */
@@ -839,8 +839,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
839839
if (phdr->p_vaddr >= seg->p_vaddr &&
840840
phdr->p_vaddr + phdr->p_memsz <=
841841
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;
844844

845845
params->dynamic_addr =
846846
(phdr->p_vaddr - seg->p_vaddr) +
@@ -850,11 +850,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
850850
* one item, and that the last item is a NULL
851851
* entry */
852852
if (phdr->p_memsz == 0 ||
853-
phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
853+
phdr->p_memsz % sizeof(Elf_Dyn) != 0)
854854
goto dynamic_error;
855855

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;
858858
if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
859859
d_tag != 0)
860860
goto dynamic_error;
@@ -923,8 +923,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
923923
struct file *file,
924924
struct mm_struct *mm)
925925
{
926-
struct elf32_fdpic_loadseg *seg;
927-
struct elf32_phdr *phdr;
926+
struct elf_fdpic_loadseg *seg;
927+
struct elf_phdr *phdr;
928928
unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0;
929929
int loop, ret;
930930

@@ -1007,8 +1007,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
10071007
struct file *file,
10081008
struct mm_struct *mm)
10091009
{
1010-
struct elf32_fdpic_loadseg *seg;
1011-
struct elf32_phdr *phdr;
1010+
struct elf_fdpic_loadseg *seg;
1011+
struct elf_phdr *phdr;
10121012
unsigned long load_addr, delta_vaddr;
10131013
int loop, dvset;
10141014

include/linux/elf-fdpic.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@
1010

1111
#include <uapi/linux/elf-fdpic.h>
1212

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+
1325
/*
1426
* binfmt binary parameters structure
1527
*/
1628
struct elf_fdpic_params {
1729
struct elfhdr hdr; /* ref copy of ELF header */
1830
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 */
2032
unsigned long elfhdr_addr; /* mapped ELF header user address */
2133
unsigned long ph_addr; /* mapped PT_PHDR user address */
2234
unsigned long map_addr; /* mapped loadmap user address */

include/uapi/linux/elf-fdpic.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
3232

3333
#define ELF32_FDPIC_LOADMAP_VERSION 0x0000
3434

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+
3550
#endif /* _UAPI_LINUX_ELF_FDPIC_H */

0 commit comments

Comments
 (0)