2023-02-28 13:52:35

by Greg Ungerer

[permalink] [raw]
Subject: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

The following changes add the ability to run ELF format binaries when
running RISC-V in nommu mode. That support is actually part of the
ELF-FDPIC loader, so these changes are all about making that work on
RISC-V.

The first issue to deal with is making the ELF-FDPIC loader capable of
handling 64-bit ELF files. As coded right now it only supports 32-bit
ELF files.

Secondly some changes are required to enable and compile the ELF-FDPIC
loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
user space when execing the new program.

These changes have not been used to run actual ELF-FDPIC binaries.
It is used to load and run normal ELF - compiled -pie format. Though the
underlying changes are expected to work with full ELF-FDPIC binaries if
or when that is supported on RISC-V in gcc.

To avoid needing changes to the C-library (tested with uClibc-ng
currently) there is a simple runtime dynamic loader (interpreter)
available to do the final relocations, https://github.com/gregungerer/uldso.
The nice thing about doing it this way is that the same program
binary can also be loaded with the usual ELF loader in MMU linux.

The motivation here is to provide an easy to use alternative to the
flat format binaries normally used for RISC-V nommu based systems.

Signed-off-by: Greg Ungerer <[email protected]>
---

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 -
fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++------------------
include/linux/elf-fdpic.h | 14 +++++++++++-
include/uapi/linux/elf-fdpic.h | 15 +++++++++++++
7 files changed, 67 insertions(+), 22 deletions(-)




2023-02-28 13:52:47

by Greg Ungerer

[permalink] [raw]
Subject: [PATCH 1/2] 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 <[email protected]>
---
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 a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
@@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
sp &= ~7UL;

/* stack the load map(s) */
- len = sizeof(struct elf32_fdpic_loadmap);
- len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
+ len = sizeof(struct elf_fdpic_loadmap);
+ len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
sp = (sp - len) & ~7UL;
exec_params->map_addr = sp;

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

if (interp_params->loadmap) {
- len = sizeof(struct elf32_fdpic_loadmap);
- len += sizeof(struct elf32_fdpic_loadseg) *
+ len = sizeof(struct elf_fdpic_loadmap);
+ len += sizeof(struct elf_fdpic_loadseg) *
interp_params->loadmap->nsegs;
sp = (sp - len) & ~7UL;
interp_params->map_addr = sp;
@@ -740,12 +740,12 @@ 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;
#endif
- struct elf32_fdpic_loadseg *seg;
- struct elf32_phdr *phdr;
+ struct elf_fdpic_loadseg *seg;
+ struct elf_phdr *phdr;
unsigned long load_addr, stop;
unsigned nloads, tmp;
size_t size;
@@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,

params->loadmap = loadmap;

- loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
+ loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
loadmap->nsegs = nloads;

load_addr = params->load_addr;
@@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
if (phdr->p_vaddr >= seg->p_vaddr &&
phdr->p_vaddr + phdr->p_memsz <=
seg->p_vaddr + seg->p_memsz) {
- Elf32_Dyn __user *dyn;
- Elf32_Sword d_tag;
+ Elf_Dyn __user *dyn;
+ Elf_Sword d_tag;

params->dynamic_addr =
(phdr->p_vaddr - seg->p_vaddr) +
@@ -854,11 +854,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 == 0 ||
- phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
+ phdr->p_memsz % sizeof(Elf_Dyn) != 0)
goto dynamic_error;

- tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
- dyn = (Elf32_Dyn __user *)params->dynamic_addr;
+ tmp = phdr->p_memsz / sizeof(Elf_Dyn);
+ dyn = (Elf_Dyn __user *)params->dynamic_addr;
if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
d_tag != 0)
goto dynamic_error;
@@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
int loop, ret;

@@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;

diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
index 3bea95a1af537..e533f45131945 100644
--- a/include/linux/elf-fdpic.h
+++ b/include/linux/elf-fdpic.h
@@ -10,13 +10,25 @@

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

+#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
--- a/include/uapi/linux/elf-fdpic.h
+++ b/include/uapi/linux/elf-fdpic.h
@@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {

#define ELF32_FDPIC_LOADMAP_VERSION 0x0000

+/* 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 */
--
2.25.1


2023-02-28 13:53:06

by Greg Ungerer

[permalink] [raw]
Subject: [PATCH 2/2] riscv: support the elf-fdpic binfmt loader

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

One of the interresting 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 <[email protected]>
---
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 e7acffdf21d26..95747b35d3262 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -40,6 +40,7 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
#define compat_elf_check_arch compat_elf_check_arch

#define CORE_DUMP_USE_REGSET
+#define ELF_FDPIC_CORE_EFLAGS 0
#define ELF_EXEC_PAGESIZE (PAGE_SIZE)

/*
@@ -67,6 +68,13 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
#define ELF_HWCAP (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
* specific libraries for optimization. This is more specific in
@@ -76,7 +84,6 @@ extern unsigned long elf_hwcap;

#define COMPAT_ELF_PLATFORM (NULL)

-#ifdef CONFIG_MMU
#define ARCH_DLINFO \
do { \
/* \
@@ -104,6 +111,8 @@ do { \
NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \
get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \
} 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 5ff1f19fd45c2..af3fc3fb4d1ad 100644
--- a/arch/riscv/include/asm/mmu.h
+++ b/arch/riscv/include/asm/mmu.h
@@ -22,6 +22,10 @@ typedef struct {
/* A local tlb flush is needed before user execution can resume. */
cpumask_t tlb_stale_mask;
#endif
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+ unsigned long exec_fdpic_loadmap;
+ unsigned long interp_fdpic_loadmap;
+#endif
} mm_context_t;

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 882547f6bd5c9..93a690509b133 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -10,6 +10,11 @@

#include <linux/types.h>

+#define PTRACE_GETFDPIC 31
+
+#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 93539aac0e5b2..f5693164ca9a3 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
--
2.25.1


2023-02-28 21:52:51

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
> The following changes add the ability to run ELF format binaries when
> running RISC-V in nommu mode. That support is actually part of the
> ELF-FDPIC loader, so these changes are all about making that work on
> RISC-V.
>
> The first issue to deal with is making the ELF-FDPIC loader capable of
> handling 64-bit ELF files. As coded right now it only supports 32-bit
> ELF files.
>
> Secondly some changes are required to enable and compile the ELF-FDPIC
> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
> user space when execing the new program.
>
> These changes have not been used to run actual ELF-FDPIC binaries.
> It is used to load and run normal ELF - compiled -pie format. Though the
> underlying changes are expected to work with full ELF-FDPIC binaries if
> or when that is supported on RISC-V in gcc.
>
> To avoid needing changes to the C-library (tested with uClibc-ng
> currently) there is a simple runtime dynamic loader (interpreter)
> available to do the final relocations, https://github.com/gregungerer/uldso.
> The nice thing about doing it this way is that the same program
> binary can also be loaded with the usual ELF loader in MMU linux.
>
> The motivation here is to provide an easy to use alternative to the
> flat format binaries normally used for RISC-V nommu based systems.
>
> Signed-off-by: Greg Ungerer <[email protected]>
> ---
>
> 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 -
> fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++------------------
> include/linux/elf-fdpic.h | 14 +++++++++++-
> include/uapi/linux/elf-fdpic.h | 15 +++++++++++++
> 7 files changed, 67 insertions(+), 22 deletions(-)

Adding Damien, as IIRC he's had some hacked up userspace bits for the
K210. I'm yet to get anything running, but it'd be great if we get this
to a point where I can actually boot test this on QEMU (I'm just doing
builds now).

Given that it's the second week of the merge window and this is a bunch
of new uABI it seems best to hold off until the next cycle. I poked
around and don't see anything wrong, but I'll try and take a more
detailed look after the merge window.

Thanks!

2023-02-28 22:44:53

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On Tue, 28 Feb 2023, Palmer Dabbelt wrote:

> Adding Damien, as IIRC he's had some hacked up userspace bits for the K210.
> I'm yet to get anything running, but it'd be great if we get this to a point
> where I can actually boot test this on QEMU (I'm just doing builds now).

And I'm still around should someone want to proceed with FDPIC support in
the toolchain.

Maciej

2023-02-28 22:49:19

by Damien Le Moal

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On 3/1/23 06:52, Palmer Dabbelt wrote:
> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>> The following changes add the ability to run ELF format binaries when
>> running RISC-V in nommu mode. That support is actually part of the
>> ELF-FDPIC loader, so these changes are all about making that work on
>> RISC-V.
>>
>> The first issue to deal with is making the ELF-FDPIC loader capable of
>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>> ELF files.
>>
>> Secondly some changes are required to enable and compile the ELF-FDPIC
>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>> user space when execing the new program.
>>
>> These changes have not been used to run actual ELF-FDPIC binaries.
>> It is used to load and run normal ELF - compiled -pie format. Though the
>> underlying changes are expected to work with full ELF-FDPIC binaries if
>> or when that is supported on RISC-V in gcc.
>>
>> To avoid needing changes to the C-library (tested with uClibc-ng
>> currently) there is a simple runtime dynamic loader (interpreter)
>> available to do the final relocations, https://github.com/gregungerer/uldso.
>> The nice thing about doing it this way is that the same program
>> binary can also be loaded with the usual ELF loader in MMU linux.
>>
>> The motivation here is to provide an easy to use alternative to the
>> flat format binaries normally used for RISC-V nommu based systems.
>>
>> Signed-off-by: Greg Ungerer <[email protected]>
>> ---
>>
>> 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 -
>> fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++------------------
>> include/linux/elf-fdpic.h | 14 +++++++++++-
>> include/uapi/linux/elf-fdpic.h | 15 +++++++++++++
>> 7 files changed, 67 insertions(+), 22 deletions(-)
>
> Adding Damien, as IIRC he's had some hacked up userspace bits for the
> K210. I'm yet to get anything running, but it'd be great if we get this
> to a point where I can actually boot test this on QEMU (I'm just doing
> builds now).

+Niklas

Niklas, didn't you add a nommu qemu build for buildroot ? Can't find the config
though...

>
> Given that it's the second week of the merge window and this is a bunch
> of new uABI it seems best to hold off until the next cycle. I poked
> around and don't see anything wrong, but I'll try and take a more
> detailed look after the merge window.

Does any riscv compiler support nommu fdpic now ? When doing the work on the
k210, there was no support at all, hence the statically linked user binaries
used (no shared text for libraries).


--
Damien Le Moal
Western Digital Research


2023-03-01 00:20:47

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

Hi Palmer,

On 1/3/23 07:52, Palmer Dabbelt wrote:
> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>> The following changes add the ability to run ELF format binaries when
>> running RISC-V in nommu mode. That support is actually part of the
>> ELF-FDPIC loader, so these changes are all about making that work on
>> RISC-V.
>>
>> The first issue to deal with is making the ELF-FDPIC loader capable of
>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>> ELF files.
>>
>> Secondly some changes are required to enable and compile the ELF-FDPIC
>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>> user space when execing the new program.
>>
>> These changes have not been used to run actual ELF-FDPIC binaries.
>> It is used to load and run normal ELF - compiled -pie format. Though the
>> underlying changes are expected to work with full ELF-FDPIC binaries if
>> or when that is supported on RISC-V in gcc.
>>
>> To avoid needing changes to the C-library (tested with uClibc-ng
>> currently) there is a simple runtime dynamic loader (interpreter)
>> available to do the final relocations, https://github.com/gregungerer/uldso.
>> The nice thing about doing it this way is that the same program
>> binary can also be loaded with the usual ELF loader in MMU linux.
>>
>> The motivation here is to provide an easy to use alternative to the
>> flat format binaries normally used for RISC-V nommu based systems.
>>
>> Signed-off-by: Greg Ungerer <[email protected]>
>> ---
>>
>>  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 -
>>  fs/binfmt_elf_fdpic.c                |   38 +++++++++++++++++------------------
>>  include/linux/elf-fdpic.h            |   14 +++++++++++-
>>  include/uapi/linux/elf-fdpic.h       |   15 +++++++++++++
>>  7 files changed, 67 insertions(+), 22 deletions(-)
>
> Adding Damien, as IIRC he's had some hacked up userspace bits for the K210.  I'm yet to get anything running, but it'd be great if we get this to a point where I can actually boot test this on QEMU (I'm just doing builds now).

This is a simple script I user to generate a working QEMU example:

https://raw.githubusercontent.com/gregungerer/simple-linux/master/build-riscvnommu-linux-uclibc-elf.sh

It does reference some configs here https://github.com/gregungerer/simple-linux/tree/master/configs
and this posted patchset as https://github.com/gregungerer/simple-linux/tree/master/patches (this is
just these 2 patches combined as a single patch).


> Given that it's the second week of the merge window and this is a bunch of new uABI it seems best to hold off until the next cycle.  I poked around and don't see anything wrong, but I'll try and take a more detailed look after the merge window.

Oh, yeah, no hurry.

Regards
Greg


2023-03-01 00:24:17

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

Hi Damien,

On 1/3/23 08:49, Damien Le Moal wrote:
> On 3/1/23 06:52, Palmer Dabbelt wrote:
>> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>>> The following changes add the ability to run ELF format binaries when
>>> running RISC-V in nommu mode. That support is actually part of the
>>> ELF-FDPIC loader, so these changes are all about making that work on
>>> RISC-V.
>>>
>>> The first issue to deal with is making the ELF-FDPIC loader capable of
>>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>>> ELF files.
>>>
>>> Secondly some changes are required to enable and compile the ELF-FDPIC
>>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>>> user space when execing the new program.
>>>
>>> These changes have not been used to run actual ELF-FDPIC binaries.
>>> It is used to load and run normal ELF - compiled -pie format. Though the
>>> underlying changes are expected to work with full ELF-FDPIC binaries if
>>> or when that is supported on RISC-V in gcc.
>>>
>>> To avoid needing changes to the C-library (tested with uClibc-ng
>>> currently) there is a simple runtime dynamic loader (interpreter)
>>> available to do the final relocations, https://github.com/gregungerer/uldso.
>>> The nice thing about doing it this way is that the same program
>>> binary can also be loaded with the usual ELF loader in MMU linux.
>>>
>>> The motivation here is to provide an easy to use alternative to the
>>> flat format binaries normally used for RISC-V nommu based systems.
>>>
>>> Signed-off-by: Greg Ungerer <[email protected]>
>>> ---
>>>
>>> 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 -
>>> fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++------------------
>>> include/linux/elf-fdpic.h | 14 +++++++++++-
>>> include/uapi/linux/elf-fdpic.h | 15 +++++++++++++
>>> 7 files changed, 67 insertions(+), 22 deletions(-)
>>
>> Adding Damien, as IIRC he's had some hacked up userspace bits for the
>> K210. I'm yet to get anything running, but it'd be great if we get this
>> to a point where I can actually boot test this on QEMU (I'm just doing
>> builds now).
>
> +Niklas
>
> Niklas, didn't you add a nommu qemu build for buildroot ? Can't find the config
> though...
>
>>
>> Given that it's the second week of the merge window and this is a bunch
>> of new uABI it seems best to hold off until the next cycle. I poked
>> around and don't see anything wrong, but I'll try and take a more
>> detailed look after the merge window.
>
> Does any riscv compiler support nommu fdpic now ? When doing the work on the
> k210, there was no support at all, hence the statically linked user binaries
> used (no shared text for libraries).

I was wondering if anyone was working on it. Couldn't find anything.

The way I use this support doesn't improve the statically linked situation.
The -pie ELF files are still statically linked. But it does avoid the
use of flat format binaries. That makes the toolchain generation a little
simpler.

Regards
Greg


2023-03-01 01:14:42

by Damien Le Moal

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On 3/1/23 09:24, Greg Ungerer wrote:
> Hi Damien,
>
> On 1/3/23 08:49, Damien Le Moal wrote:
>> On 3/1/23 06:52, Palmer Dabbelt wrote:
>>> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>>>> The following changes add the ability to run ELF format binaries when
>>>> running RISC-V in nommu mode. That support is actually part of the
>>>> ELF-FDPIC loader, so these changes are all about making that work on
>>>> RISC-V.
>>>>
>>>> The first issue to deal with is making the ELF-FDPIC loader capable of
>>>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>>>> ELF files.
>>>>
>>>> Secondly some changes are required to enable and compile the ELF-FDPIC
>>>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>>>> user space when execing the new program.
>>>>
>>>> These changes have not been used to run actual ELF-FDPIC binaries.
>>>> It is used to load and run normal ELF - compiled -pie format. Though the
>>>> underlying changes are expected to work with full ELF-FDPIC binaries if
>>>> or when that is supported on RISC-V in gcc.
>>>>
>>>> To avoid needing changes to the C-library (tested with uClibc-ng
>>>> currently) there is a simple runtime dynamic loader (interpreter)
>>>> available to do the final relocations, https://github.com/gregungerer/uldso.
>>>> The nice thing about doing it this way is that the same program
>>>> binary can also be loaded with the usual ELF loader in MMU linux.
>>>>
>>>> The motivation here is to provide an easy to use alternative to the
>>>> flat format binaries normally used for RISC-V nommu based systems.
>>>>
>>>> Signed-off-by: Greg Ungerer <[email protected]>
>>>> ---
>>>>
>>>> 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 -
>>>> fs/binfmt_elf_fdpic.c | 38 +++++++++++++++++------------------
>>>> include/linux/elf-fdpic.h | 14 +++++++++++-
>>>> include/uapi/linux/elf-fdpic.h | 15 +++++++++++++
>>>> 7 files changed, 67 insertions(+), 22 deletions(-)
>>>
>>> Adding Damien, as IIRC he's had some hacked up userspace bits for the
>>> K210. I'm yet to get anything running, but it'd be great if we get this
>>> to a point where I can actually boot test this on QEMU (I'm just doing
>>> builds now).
>>
>> +Niklas
>>
>> Niklas, didn't you add a nommu qemu build for buildroot ? Can't find the config
>> though...
>>
>>>
>>> Given that it's the second week of the merge window and this is a bunch
>>> of new uABI it seems best to hold off until the next cycle. I poked
>>> around and don't see anything wrong, but I'll try and take a more
>>> detailed look after the merge window.
>>
>> Does any riscv compiler support nommu fdpic now ? When doing the work on the
>> k210, there was no support at all, hence the statically linked user binaries
>> used (no shared text for libraries).
>
> I was wondering if anyone was working on it. Couldn't find anything.

Maciej (added to this thread) has done some work on gcc, but nothing that is
upstream yet.

> The way I use this support doesn't improve the statically linked situation.
> The -pie ELF files are still statically linked. But it does avoid the
> use of flat format binaries. That makes the toolchain generation a little
> simpler.

Right. I was still thinking in terms of flat bin. The keyword here is "elf"...
Need more coffe :)

We could try this using either qemu or the k210 with buildroot, with the
addition of your uldso loader. Will try to put that in the pipeline (pretty full
as usual, so may take a while).

>
> Regards
> Greg
>

--
Damien Le Moal
Western Digital Research


2023-03-01 09:46:49

by Niklas Cassel

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On Wed, Mar 01, 2023 at 07:49:05AM +0900, Damien Le Moal wrote:

(snip)

> > Adding Damien, as IIRC he's had some hacked up userspace bits for the
> > K210. I'm yet to get anything running, but it'd be great if we get this
> > to a point where I can actually boot test this on QEMU (I'm just doing
> > builds now).
>
> +Niklas
>
> Niklas, didn't you add a nommu qemu build for buildroot ? Can't find the config
> though...

Yes, I did.

In buildroot:
$ make qemu_riscv64_nommu_virt_defconfig

The QEMU command line generated by buildroot:
qemu-system-riscv64 -M virt -bios none -kernel output/images/Image -append "rootwait root=/dev/vda ro" -drive file=output/images/rootfs.ext2,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -nographic -cpu rv64,mmu=off # qemu_riscv64_nommu_virt_defconfig

Compared to a regular riscv64 QEMU command line, the relevant parameter is:
-cpu rv64,mmu=off


Kind regards,
Niklas

2023-03-15 03:58:40

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On Tue, 28 Feb 2023 16:20:35 PST (-0800), [email protected] wrote:
> Hi Palmer,
>
> On 1/3/23 07:52, Palmer Dabbelt wrote:
>> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>>> The following changes add the ability to run ELF format binaries when
>>> running RISC-V in nommu mode. That support is actually part of the
>>> ELF-FDPIC loader, so these changes are all about making that work on
>>> RISC-V.
>>>
>>> The first issue to deal with is making the ELF-FDPIC loader capable of
>>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>>> ELF files.
>>>
>>> Secondly some changes are required to enable and compile the ELF-FDPIC
>>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>>> user space when execing the new program.
>>>
>>> These changes have not been used to run actual ELF-FDPIC binaries.
>>> It is used to load and run normal ELF - compiled -pie format. Though the
>>> underlying changes are expected to work with full ELF-FDPIC binaries if
>>> or when that is supported on RISC-V in gcc.
>>>
>>> To avoid needing changes to the C-library (tested with uClibc-ng
>>> currently) there is a simple runtime dynamic loader (interpreter)
>>> available to do the final relocations, https://github.com/gregungerer/uldso.
>>> The nice thing about doing it this way is that the same program
>>> binary can also be loaded with the usual ELF loader in MMU linux.
>>>
>>> The motivation here is to provide an easy to use alternative to the
>>> flat format binaries normally used for RISC-V nommu based systems.
>>>
>>> Signed-off-by: Greg Ungerer <[email protected]>
>>> ---
>>>
>>>  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 -
>>>  fs/binfmt_elf_fdpic.c                |   38 +++++++++++++++++------------------
>>>  include/linux/elf-fdpic.h            |   14 +++++++++++-
>>>  include/uapi/linux/elf-fdpic.h       |   15 +++++++++++++
>>>  7 files changed, 67 insertions(+), 22 deletions(-)
>>
>> Adding Damien, as IIRC he's had some hacked up userspace bits for the K210.  I'm yet to get anything running, but it'd be great if we get this to a point where I can actually boot test this on QEMU (I'm just doing builds now).
>
> This is a simple script I user to generate a working QEMU example:
>
> https://raw.githubusercontent.com/gregungerer/simple-linux/master/build-riscvnommu-linux-uclibc-elf.sh
>
> It does reference some configs here https://github.com/gregungerer/simple-linux/tree/master/configs
> and this posted patchset as https://github.com/gregungerer/simple-linux/tree/master/patches (this is
> just these 2 patches combined as a single patch).
>
>
>> Given that it's the second week of the merge window and this is a bunch of new uABI it seems best to hold off until the next cycle.  I poked around and don't see anything wrong, but I'll try and take a more detailed look after the merge window.
>
> Oh, yeah, no hurry.

Maciej and Damien: I'm fine taking this, but not in any rush. I'd
rather get the uABI right if things are still in flight, but if we're
all just waiting for something to get merged first then I'm fine with
that being Linux.

>
> Regards
> Greg

2023-03-15 04:14:12

by Damien Le Moal

[permalink] [raw]
Subject: Re: [PATCH 0/2] riscv: support ELF format binaries in nommu mode

On 3/15/23 12:58, Palmer Dabbelt wrote:
> On Tue, 28 Feb 2023 16:20:35 PST (-0800), [email protected] wrote:
>> Hi Palmer,
>>
>> On 1/3/23 07:52, Palmer Dabbelt wrote:
>>> On Tue, 28 Feb 2023 05:51:24 PST (-0800), [email protected] wrote:
>>>> The following changes add the ability to run ELF format binaries when
>>>> running RISC-V in nommu mode. That support is actually part of the
>>>> ELF-FDPIC loader, so these changes are all about making that work on
>>>> RISC-V.
>>>>
>>>> The first issue to deal with is making the ELF-FDPIC loader capable of
>>>> handling 64-bit ELF files. As coded right now it only supports 32-bit
>>>> ELF files.
>>>>
>>>> Secondly some changes are required to enable and compile the ELF-FDPIC
>>>> loader on RISC-V and to pass the ELF-FDPIC mapping addresses through to
>>>> user space when execing the new program.
>>>>
>>>> These changes have not been used to run actual ELF-FDPIC binaries.
>>>> It is used to load and run normal ELF - compiled -pie format. Though the
>>>> underlying changes are expected to work with full ELF-FDPIC binaries if
>>>> or when that is supported on RISC-V in gcc.
>>>>
>>>> To avoid needing changes to the C-library (tested with uClibc-ng
>>>> currently) there is a simple runtime dynamic loader (interpreter)
>>>> available to do the final relocations, https://github.com/gregungerer/uldso.
>>>> The nice thing about doing it this way is that the same program
>>>> binary can also be loaded with the usual ELF loader in MMU linux.
>>>>
>>>> The motivation here is to provide an easy to use alternative to the
>>>> flat format binaries normally used for RISC-V nommu based systems.
>>>>
>>>> Signed-off-by: Greg Ungerer <[email protected]>
>>>> ---
>>>>
>>>>  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 -
>>>>  fs/binfmt_elf_fdpic.c                |   38 +++++++++++++++++------------------
>>>>  include/linux/elf-fdpic.h            |   14 +++++++++++-
>>>>  include/uapi/linux/elf-fdpic.h       |   15 +++++++++++++
>>>>  7 files changed, 67 insertions(+), 22 deletions(-)
>>>
>>> Adding Damien, as IIRC he's had some hacked up userspace bits for the K210.  I'm yet to get anything running, but it'd be great if we get this to a point where I can actually boot test this on QEMU (I'm just doing builds now).
>>
>> This is a simple script I user to generate a working QEMU example:
>>
>> https://raw.githubusercontent.com/gregungerer/simple-linux/master/build-riscvnommu-linux-uclibc-elf.sh
>>
>> It does reference some configs here https://github.com/gregungerer/simple-linux/tree/master/configs
>> and this posted patchset as https://github.com/gregungerer/simple-linux/tree/master/patches (this is
>> just these 2 patches combined as a single patch).
>>
>>
>>> Given that it's the second week of the merge window and this is a bunch of new uABI it seems best to hold off until the next cycle.  I poked around and don't see anything wrong, but I'll try and take a more detailed look after the merge window.
>>
>> Oh, yeah, no hurry.
>
> Maciej and Damien: I'm fine taking this, but not in any rush. I'd
> rather get the uABI right if things are still in flight, but if we're
> all just waiting for something to get merged first then I'm fine with
> that being Linux.

I did not try Gerg script with the k210. No time right now.
But if it works with QEMU, should be fine.

>
>>
>> Regards
>> Greg

--
Damien Le Moal
Western Digital Research


2023-03-21 23:07:18

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems

On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
> 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 <[email protected]>
> ---
> 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(-)

Adding some of the binfmt/fs folks, who weren't directly on the mail.
It's looking like we're generally OK with this in RISC-V land, though
there's still no userspace posted. I don't think there's any rush here
and it might be prudent to wait for userspace to start going through a
bit of a review, but figured I'd at least poke everyone to see if
there's any thoughts.

I'm fine either way, so

Acked-by: Palmer Dabbelt <[email protected]>

if that helps any. Also happy to take this through the RISC-V tree
along with the other if that's easier, but again no rush.

>
> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
> sp &= ~7UL;
>
> /* stack the load map(s) */
> - len = sizeof(struct elf32_fdpic_loadmap);
> - len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
> + len = sizeof(struct elf_fdpic_loadmap);
> + len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
> sp = (sp - len) & ~7UL;
> exec_params->map_addr = sp;
>
> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
> current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>
> if (interp_params->loadmap) {
> - len = sizeof(struct elf32_fdpic_loadmap);
> - len += sizeof(struct elf32_fdpic_loadseg) *
> + len = sizeof(struct elf_fdpic_loadmap);
> + len += sizeof(struct elf_fdpic_loadseg) *
> interp_params->loadmap->nsegs;
> sp = (sp - len) & ~7UL;
> interp_params->map_addr = sp;
> @@ -740,12 +740,12 @@ 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;
> #endif
> - struct elf32_fdpic_loadseg *seg;
> - struct elf32_phdr *phdr;
> + struct elf_fdpic_loadseg *seg;
> + struct elf_phdr *phdr;
> unsigned long load_addr, stop;
> unsigned nloads, tmp;
> size_t size;
> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>
> params->loadmap = loadmap;
>
> - loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
> + loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
> loadmap->nsegs = nloads;
>
> load_addr = params->load_addr;
> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
> if (phdr->p_vaddr >= seg->p_vaddr &&
> phdr->p_vaddr + phdr->p_memsz <=
> seg->p_vaddr + seg->p_memsz) {
> - Elf32_Dyn __user *dyn;
> - Elf32_Sword d_tag;
> + Elf_Dyn __user *dyn;
> + Elf_Sword d_tag;
>
> params->dynamic_addr =
> (phdr->p_vaddr - seg->p_vaddr) +
> @@ -854,11 +854,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 == 0 ||
> - phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
> + phdr->p_memsz % sizeof(Elf_Dyn) != 0)
> goto dynamic_error;
>
> - tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
> - dyn = (Elf32_Dyn __user *)params->dynamic_addr;
> + tmp = phdr->p_memsz / sizeof(Elf_Dyn);
> + dyn = (Elf_Dyn __user *)params->dynamic_addr;
> if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
> d_tag != 0)
> goto dynamic_error;
> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
> int loop, ret;
>
> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>
> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
> index 3bea95a1af537..e533f45131945 100644
> --- a/include/linux/elf-fdpic.h
> +++ b/include/linux/elf-fdpic.h
> @@ -10,13 +10,25 @@
>
> #include <uapi/linux/elf-fdpic.h>
>
> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
> --- a/include/uapi/linux/elf-fdpic.h
> +++ b/include/uapi/linux/elf-fdpic.h
> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>
> #define ELF32_FDPIC_LOADMAP_VERSION 0x0000
>
> +/* 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 */

2023-03-29 13:53:04

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems


On 22/3/23 08:49, Palmer Dabbelt wrote:
> On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
>> 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 <[email protected]>
>> ---
>>  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(-)
>
> Adding some of the binfmt/fs folks, who weren't directly on the mail. It's looking like we're generally OK with this in RISC-V land, though there's still no userspace posted.  I don't think there's any rush here and it might be prudent to wait for userspace to start going through a bit of a review, but figured I'd at least poke everyone to see if there's any thoughts.
>
> I'm fine either way, so
> Acked-by: Palmer Dabbelt <[email protected]>
>
> if that helps any.  Also happy to take this through the RISC-V tree along with the other if that's easier, but again no rush.

Just following up. I haven't seen any feedback on this - did I miss any?

Regards
Greg


>> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
>> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
>> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>      sp &= ~7UL;
>>
>>      /* stack the load map(s) */
>> -    len = sizeof(struct elf32_fdpic_loadmap);
>> -    len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
>> +    len = sizeof(struct elf_fdpic_loadmap);
>> +    len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>      sp = (sp - len) & ~7UL;
>>      exec_params->map_addr = sp;
>>
>> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>      current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>>
>>      if (interp_params->loadmap) {
>> -        len = sizeof(struct elf32_fdpic_loadmap);
>> -        len += sizeof(struct elf32_fdpic_loadseg) *
>> +        len = sizeof(struct elf_fdpic_loadmap);
>> +        len += sizeof(struct elf_fdpic_loadseg) *
>>              interp_params->loadmap->nsegs;
>>          sp = (sp - len) & ~7UL;
>>          interp_params->map_addr = sp;
>> @@ -740,12 +740,12 @@ 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;
>>  #endif
>> -    struct elf32_fdpic_loadseg *seg;
>> -    struct elf32_phdr *phdr;
>> +    struct elf_fdpic_loadseg *seg;
>> +    struct elf_phdr *phdr;
>>      unsigned long load_addr, stop;
>>      unsigned nloads, tmp;
>>      size_t size;
>> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>
>>      params->loadmap = loadmap;
>>
>> -    loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
>> +    loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
>>      loadmap->nsegs = nloads;
>>
>>      load_addr = params->load_addr;
>> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>              if (phdr->p_vaddr >= seg->p_vaddr &&
>>                  phdr->p_vaddr + phdr->p_memsz <=
>>                  seg->p_vaddr + seg->p_memsz) {
>> -                Elf32_Dyn __user *dyn;
>> -                Elf32_Sword d_tag;
>> +                Elf_Dyn __user *dyn;
>> +                Elf_Sword d_tag;
>>
>>                  params->dynamic_addr =
>>                      (phdr->p_vaddr - seg->p_vaddr) +
>> @@ -854,11 +854,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 == 0 ||
>> -                    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
>> +                    phdr->p_memsz % sizeof(Elf_Dyn) != 0)
>>                      goto dynamic_error;
>>
>> -                tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
>> -                dyn = (Elf32_Dyn __user *)params->dynamic_addr;
>> +                tmp = phdr->p_memsz / sizeof(Elf_Dyn);
>> +                dyn = (Elf_Dyn __user *)params->dynamic_addr;
>>                  if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
>>                      d_tag != 0)
>>                      goto dynamic_error;
>> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
>>      int loop, ret;
>>
>> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>>
>> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
>> index 3bea95a1af537..e533f45131945 100644
>> --- a/include/linux/elf-fdpic.h
>> +++ b/include/linux/elf-fdpic.h
>> @@ -10,13 +10,25 @@
>>
>>  #include <uapi/linux/elf-fdpic.h>
>>
>> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
>> --- a/include/uapi/linux/elf-fdpic.h
>> +++ b/include/uapi/linux/elf-fdpic.h
>> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>>
>>  #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
>>
>> +/* 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 */
>

2023-04-19 03:29:54

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems

On Wed, 29 Mar 2023 06:48:55 PDT (-0700), [email protected] wrote:
>
> On 22/3/23 08:49, Palmer Dabbelt wrote:
>> On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
>>> 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 <[email protected]>
>>> ---
>>>  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(-)
>>
>> Adding some of the binfmt/fs folks, who weren't directly on the mail. It's looking like we're generally OK with this in RISC-V land, though there's still no userspace posted.  I don't think there's any rush here and it might be prudent to wait for userspace to start going through a bit of a review, but figured I'd at least poke everyone to see if there's any thoughts.
>>
>> I'm fine either way, so
>> Acked-by: Palmer Dabbelt <[email protected]>
>>
>> if that helps any.  Also happy to take this through the RISC-V tree along with the other if that's easier, but again no rush.
>
> Just following up. I haven't seen any feedback on this - did I miss any?

If you did then I did too. I'm not really sure what to do here: it
looks fine to me, but it's not really my area so I'd prefer to have
someone who understands this stuff a bit better chime in.

It looks like some Arm patches recently went in through that tree,
though, so maybe that's how things are supposed to go here?

>
> Regards
> Greg
>
>
>>> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
>>> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
>>> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>      sp &= ~7UL;
>>>
>>>      /* stack the load map(s) */
>>> -    len = sizeof(struct elf32_fdpic_loadmap);
>>> -    len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>> +    len = sizeof(struct elf_fdpic_loadmap);
>>> +    len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>      sp = (sp - len) & ~7UL;
>>>      exec_params->map_addr = sp;
>>>
>>> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>      current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>>>
>>>      if (interp_params->loadmap) {
>>> -        len = sizeof(struct elf32_fdpic_loadmap);
>>> -        len += sizeof(struct elf32_fdpic_loadseg) *
>>> +        len = sizeof(struct elf_fdpic_loadmap);
>>> +        len += sizeof(struct elf_fdpic_loadseg) *
>>>              interp_params->loadmap->nsegs;
>>>          sp = (sp - len) & ~7UL;
>>>          interp_params->map_addr = sp;
>>> @@ -740,12 +740,12 @@ 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;
>>>  #endif
>>> -    struct elf32_fdpic_loadseg *seg;
>>> -    struct elf32_phdr *phdr;
>>> +    struct elf_fdpic_loadseg *seg;
>>> +    struct elf_phdr *phdr;
>>>      unsigned long load_addr, stop;
>>>      unsigned nloads, tmp;
>>>      size_t size;
>>> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>
>>>      params->loadmap = loadmap;
>>>
>>> -    loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
>>> +    loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
>>>      loadmap->nsegs = nloads;
>>>
>>>      load_addr = params->load_addr;
>>> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>              if (phdr->p_vaddr >= seg->p_vaddr &&
>>>                  phdr->p_vaddr + phdr->p_memsz <=
>>>                  seg->p_vaddr + seg->p_memsz) {
>>> -                Elf32_Dyn __user *dyn;
>>> -                Elf32_Sword d_tag;
>>> +                Elf_Dyn __user *dyn;
>>> +                Elf_Sword d_tag;
>>>
>>>                  params->dynamic_addr =
>>>                      (phdr->p_vaddr - seg->p_vaddr) +
>>> @@ -854,11 +854,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 == 0 ||
>>> -                    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
>>> +                    phdr->p_memsz % sizeof(Elf_Dyn) != 0)
>>>                      goto dynamic_error;
>>>
>>> -                tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
>>> -                dyn = (Elf32_Dyn __user *)params->dynamic_addr;
>>> +                tmp = phdr->p_memsz / sizeof(Elf_Dyn);
>>> +                dyn = (Elf_Dyn __user *)params->dynamic_addr;
>>>                  if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
>>>                      d_tag != 0)
>>>                      goto dynamic_error;
>>> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
>>>      int loop, ret;
>>>
>>> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>>>
>>> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
>>> index 3bea95a1af537..e533f45131945 100644
>>> --- a/include/linux/elf-fdpic.h
>>> +++ b/include/linux/elf-fdpic.h
>>> @@ -10,13 +10,25 @@
>>>
>>>  #include <uapi/linux/elf-fdpic.h>
>>>
>>> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
>>> --- a/include/uapi/linux/elf-fdpic.h
>>> +++ b/include/uapi/linux/elf-fdpic.h
>>> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>>>
>>>  #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
>>>
>>> +/* 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 */
>>

2023-04-20 15:12:16

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems

Hi Palmer,

On 19/4/23 13:27, Palmer Dabbelt wrote:
> On Wed, 29 Mar 2023 06:48:55 PDT (-0700), [email protected] wrote:
>>
>> On 22/3/23 08:49, Palmer Dabbelt wrote:
>>> On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
>>>> 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 <[email protected]>
>>>> ---
>>>>  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(-)
>>>
>>> Adding some of the binfmt/fs folks, who weren't directly on the mail. It's looking like we're generally OK with this in RISC-V land, though there's still no userspace posted.  I don't think there's any rush here and it might be prudent to wait for userspace to start going through a bit of a review, but figured I'd at least poke everyone to see if there's any thoughts.
>>>
>>> I'm fine either way, so
>>> Acked-by: Palmer Dabbelt <[email protected]>
>>>
>>> if that helps any.  Also happy to take this through the RISC-V tree along with the other if that's easier, but again no rush.
>>
>> Just following up. I haven't seen any feedback on this - did I miss any?
>
> If you did then I did too.  I'm not really sure what to do here: it looks fine to me, but it's not really my area so I'd prefer to have someone who understands this stuff a bit better chime in.
>
> It looks like some Arm patches recently went in through that tree, though, so maybe that's how things are supposed to go here?

There doesn't seem to be anyone who is clearly the designated maintainer
for binfmt_elf_fdpic, or even just sheparding fixes for it. It mostly seems
to be tree-wide changes and cleanups that are getting done to it.

So I have no idea... I have at least one fix inside binfmt_elf_fdpic.c for
ARM architecture that I am preparing now too, not sure how that is going to
go either.

Regards
Greg



>>>> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
>>>> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
>>>> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>      sp &= ~7UL;
>>>>
>>>>      /* stack the load map(s) */
>>>> -    len = sizeof(struct elf32_fdpic_loadmap);
>>>> -    len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>> +    len = sizeof(struct elf_fdpic_loadmap);
>>>> +    len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>>      sp = (sp - len) & ~7UL;
>>>>      exec_params->map_addr = sp;
>>>>
>>>> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>      current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>>>>
>>>>      if (interp_params->loadmap) {
>>>> -        len = sizeof(struct elf32_fdpic_loadmap);
>>>> -        len += sizeof(struct elf32_fdpic_loadseg) *
>>>> +        len = sizeof(struct elf_fdpic_loadmap);
>>>> +        len += sizeof(struct elf_fdpic_loadseg) *
>>>>              interp_params->loadmap->nsegs;
>>>>          sp = (sp - len) & ~7UL;
>>>>          interp_params->map_addr = sp;
>>>> @@ -740,12 +740,12 @@ 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;
>>>>  #endif
>>>> -    struct elf32_fdpic_loadseg *seg;
>>>> -    struct elf32_phdr *phdr;
>>>> +    struct elf_fdpic_loadseg *seg;
>>>> +    struct elf_phdr *phdr;
>>>>      unsigned long load_addr, stop;
>>>>      unsigned nloads, tmp;
>>>>      size_t size;
>>>> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>
>>>>      params->loadmap = loadmap;
>>>>
>>>> -    loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
>>>> +    loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
>>>>      loadmap->nsegs = nloads;
>>>>
>>>>      load_addr = params->load_addr;
>>>> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>              if (phdr->p_vaddr >= seg->p_vaddr &&
>>>>                  phdr->p_vaddr + phdr->p_memsz <=
>>>>                  seg->p_vaddr + seg->p_memsz) {
>>>> -                Elf32_Dyn __user *dyn;
>>>> -                Elf32_Sword d_tag;
>>>> +                Elf_Dyn __user *dyn;
>>>> +                Elf_Sword d_tag;
>>>>
>>>>                  params->dynamic_addr =
>>>>                      (phdr->p_vaddr - seg->p_vaddr) +
>>>> @@ -854,11 +854,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 == 0 ||
>>>> -                    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
>>>> +                    phdr->p_memsz % sizeof(Elf_Dyn) != 0)
>>>>                      goto dynamic_error;
>>>>
>>>> -                tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
>>>> -                dyn = (Elf32_Dyn __user *)params->dynamic_addr;
>>>> +                tmp = phdr->p_memsz / sizeof(Elf_Dyn);
>>>> +                dyn = (Elf_Dyn __user *)params->dynamic_addr;
>>>>                  if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
>>>>                      d_tag != 0)
>>>>                      goto dynamic_error;
>>>> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
>>>>      int loop, ret;
>>>>
>>>> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>>>>
>>>> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
>>>> index 3bea95a1af537..e533f45131945 100644
>>>> --- a/include/linux/elf-fdpic.h
>>>> +++ b/include/linux/elf-fdpic.h
>>>> @@ -10,13 +10,25 @@
>>>>
>>>>  #include <uapi/linux/elf-fdpic.h>
>>>>
>>>> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
>>>> --- a/include/uapi/linux/elf-fdpic.h
>>>> +++ b/include/uapi/linux/elf-fdpic.h
>>>> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>>>>
>>>>  #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
>>>>
>>>> +/* 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 */
>>>

2023-07-11 00:07:15

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems

On Thu, 20 Apr 2023 07:58:29 PDT (-0700), [email protected] wrote:
> Hi Palmer,
>
> On 19/4/23 13:27, Palmer Dabbelt wrote:
>> On Wed, 29 Mar 2023 06:48:55 PDT (-0700), [email protected] wrote:
>>>
>>> On 22/3/23 08:49, Palmer Dabbelt wrote:
>>>> On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
>>>>> 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 <[email protected]>
>>>>> ---
>>>>>  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(-)
>>>>
>>>> Adding some of the binfmt/fs folks, who weren't directly on the mail. It's looking like we're generally OK with this in RISC-V land, though there's still no userspace posted.  I don't think there's any rush here and it might be prudent to wait for userspace to start going through a bit of a review, but figured I'd at least poke everyone to see if there's any thoughts.
>>>>
>>>> I'm fine either way, so
>>>> Acked-by: Palmer Dabbelt <[email protected]>
>>>>
>>>> if that helps any.  Also happy to take this through the RISC-V tree along with the other if that's easier, but again no rush.
>>>
>>> Just following up. I haven't seen any feedback on this - did I miss any?
>>
>> If you did then I did too.  I'm not really sure what to do here: it looks fine to me, but it's not really my area so I'd prefer to have someone who understands this stuff a bit better chime in.
>>
>> It looks like some Arm patches recently went in through that tree, though, so maybe that's how things are supposed to go here?
>
> There doesn't seem to be anyone who is clearly the designated maintainer
> for binfmt_elf_fdpic, or even just sheparding fixes for it. It mostly seems
> to be tree-wide changes and cleanups that are getting done to it.
>
> So I have no idea... I have at least one fix inside binfmt_elf_fdpic.c for
> ARM architecture that I am preparing now too, not sure how that is going to
> go either.

Looks like maybe nobody is taking these, then? Certainly nobody has
chimed in. There's been some minor conflicts over the past few months,
do you mind sending a v2? If nobody says anything on that I'll just
take it via the RISC-V tree.

>
> Regards
> Greg
>
>
>
>>>>> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
>>>>> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
>>>>> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>>      sp &= ~7UL;
>>>>>
>>>>>      /* stack the load map(s) */
>>>>> -    len = sizeof(struct elf32_fdpic_loadmap);
>>>>> -    len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>>> +    len = sizeof(struct elf_fdpic_loadmap);
>>>>> +    len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>>>      sp = (sp - len) & ~7UL;
>>>>>      exec_params->map_addr = sp;
>>>>>
>>>>> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>>      current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>>>>>
>>>>>      if (interp_params->loadmap) {
>>>>> -        len = sizeof(struct elf32_fdpic_loadmap);
>>>>> -        len += sizeof(struct elf32_fdpic_loadseg) *
>>>>> +        len = sizeof(struct elf_fdpic_loadmap);
>>>>> +        len += sizeof(struct elf_fdpic_loadseg) *
>>>>>              interp_params->loadmap->nsegs;
>>>>>          sp = (sp - len) & ~7UL;
>>>>>          interp_params->map_addr = sp;
>>>>> @@ -740,12 +740,12 @@ 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;
>>>>>  #endif
>>>>> -    struct elf32_fdpic_loadseg *seg;
>>>>> -    struct elf32_phdr *phdr;
>>>>> +    struct elf_fdpic_loadseg *seg;
>>>>> +    struct elf_phdr *phdr;
>>>>>      unsigned long load_addr, stop;
>>>>>      unsigned nloads, tmp;
>>>>>      size_t size;
>>>>> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>>
>>>>>      params->loadmap = loadmap;
>>>>>
>>>>> -    loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
>>>>> +    loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
>>>>>      loadmap->nsegs = nloads;
>>>>>
>>>>>      load_addr = params->load_addr;
>>>>> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>>              if (phdr->p_vaddr >= seg->p_vaddr &&
>>>>>                  phdr->p_vaddr + phdr->p_memsz <=
>>>>>                  seg->p_vaddr + seg->p_memsz) {
>>>>> -                Elf32_Dyn __user *dyn;
>>>>> -                Elf32_Sword d_tag;
>>>>> +                Elf_Dyn __user *dyn;
>>>>> +                Elf_Sword d_tag;
>>>>>
>>>>>                  params->dynamic_addr =
>>>>>                      (phdr->p_vaddr - seg->p_vaddr) +
>>>>> @@ -854,11 +854,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 == 0 ||
>>>>> -                    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
>>>>> +                    phdr->p_memsz % sizeof(Elf_Dyn) != 0)
>>>>>                      goto dynamic_error;
>>>>>
>>>>> -                tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
>>>>> -                dyn = (Elf32_Dyn __user *)params->dynamic_addr;
>>>>> +                tmp = phdr->p_memsz / sizeof(Elf_Dyn);
>>>>> +                dyn = (Elf_Dyn __user *)params->dynamic_addr;
>>>>>                  if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
>>>>>                      d_tag != 0)
>>>>>                      goto dynamic_error;
>>>>> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
>>>>>      int loop, ret;
>>>>>
>>>>> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>>>>>
>>>>> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
>>>>> index 3bea95a1af537..e533f45131945 100644
>>>>> --- a/include/linux/elf-fdpic.h
>>>>> +++ b/include/linux/elf-fdpic.h
>>>>> @@ -10,13 +10,25 @@
>>>>>
>>>>>  #include <uapi/linux/elf-fdpic.h>
>>>>>
>>>>> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
>>>>> --- a/include/uapi/linux/elf-fdpic.h
>>>>> +++ b/include/uapi/linux/elf-fdpic.h
>>>>> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>>>>>
>>>>>  #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
>>>>>
>>>>> +/* 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 */
>>>>

2023-07-11 12:08:26

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 1/2] binfmt_elf_fdpic: support 64-bit systems

Hi Palmer,

On 11/7/23 09:18, Palmer Dabbelt wrote:
> On Thu, 20 Apr 2023 07:58:29 PDT (-0700), [email protected] wrote:
>> Hi Palmer,
>>
>> On 19/4/23 13:27, Palmer Dabbelt wrote:
>>> On Wed, 29 Mar 2023 06:48:55 PDT (-0700), [email protected] wrote:
>>>>
>>>> On 22/3/23 08:49, Palmer Dabbelt wrote:
>>>>> On Tue, 28 Feb 2023 05:51:25 PST (-0800), [email protected] wrote:
>>>>>> 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 <[email protected]>
>>>>>> ---
>>>>>>  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(-)
>>>>>
>>>>> Adding some of the binfmt/fs folks, who weren't directly on the mail. It's looking like we're generally OK with this in RISC-V land, though there's still no userspace posted.  I don't think there's any rush here and it might be prudent to wait for userspace to start going through a bit of a review, but figured I'd at least poke everyone to see if there's any thoughts.
>>>>>
>>>>> I'm fine either way, so
>>>>> Acked-by: Palmer Dabbelt <[email protected]>
>>>>>
>>>>> if that helps any.  Also happy to take this through the RISC-V tree along with the other if that's easier, but again no rush.
>>>>
>>>> Just following up. I haven't seen any feedback on this - did I miss any?
>>>
>>> If you did then I did too.  I'm not really sure what to do here: it looks fine to me, but it's not really my area so I'd prefer to have someone who understands this stuff a bit better chime in.
>>>
>>> It looks like some Arm patches recently went in through that tree, though, so maybe that's how things are supposed to go here?
>>
>> There doesn't seem to be anyone who is clearly the designated maintainer
>> for binfmt_elf_fdpic, or even just sheparding fixes for it. It mostly seems
>> to be tree-wide changes and cleanups that are getting done to it.
>>
>> So I have no idea... I have at least one fix inside binfmt_elf_fdpic.c for
>> ARM architecture that I am preparing now too, not sure how that is going to
>> go either.
>
> Looks like maybe nobody is taking these, then?  Certainly nobody has chimed in.

Yes, its been complete silence


>  There's been some minor conflicts over the past few months, do you mind sending a v2?  If nobody says anything on that I'll just take it via the RISC-V tree.

Sounds like a good plan.
I will send out a v2 today.

Regards
Greg




>>>>>> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
>>>>>> index a05eafcacfb27..2eea6dd429fd6 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 = params->hdr.e_phoff;
>>>>>> @@ -560,8 +560,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>>>      sp &= ~7UL;
>>>>>>
>>>>>>      /* stack the load map(s) */
>>>>>> -    len = sizeof(struct elf32_fdpic_loadmap);
>>>>>> -    len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>>>> +    len = sizeof(struct elf_fdpic_loadmap);
>>>>>> +    len += sizeof(struct elf_fdpic_loadseg) * exec_params->loadmap->nsegs;
>>>>>>      sp = (sp - len) & ~7UL;
>>>>>>      exec_params->map_addr = sp;
>>>>>>
>>>>>> @@ -571,8 +571,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
>>>>>>      current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
>>>>>>
>>>>>>      if (interp_params->loadmap) {
>>>>>> -        len = sizeof(struct elf32_fdpic_loadmap);
>>>>>> -        len += sizeof(struct elf32_fdpic_loadseg) *
>>>>>> +        len = sizeof(struct elf_fdpic_loadmap);
>>>>>> +        len += sizeof(struct elf_fdpic_loadseg) *
>>>>>>              interp_params->loadmap->nsegs;
>>>>>>          sp = (sp - len) & ~7UL;
>>>>>>          interp_params->map_addr = sp;
>>>>>> @@ -740,12 +740,12 @@ 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;
>>>>>>  #endif
>>>>>> -    struct elf32_fdpic_loadseg *seg;
>>>>>> -    struct elf32_phdr *phdr;
>>>>>> +    struct elf_fdpic_loadseg *seg;
>>>>>> +    struct elf_phdr *phdr;
>>>>>>      unsigned long load_addr, stop;
>>>>>>      unsigned nloads, tmp;
>>>>>>      size_t size;
>>>>>> @@ -767,7 +767,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>>>
>>>>>>      params->loadmap = loadmap;
>>>>>>
>>>>>> -    loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
>>>>>> +    loadmap->version = ELF_FDPIC_LOADMAP_VERSION;
>>>>>>      loadmap->nsegs = nloads;
>>>>>>
>>>>>>      load_addr = params->load_addr;
>>>>>> @@ -843,8 +843,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>>>>>>              if (phdr->p_vaddr >= seg->p_vaddr &&
>>>>>>                  phdr->p_vaddr + phdr->p_memsz <=
>>>>>>                  seg->p_vaddr + seg->p_memsz) {
>>>>>> -                Elf32_Dyn __user *dyn;
>>>>>> -                Elf32_Sword d_tag;
>>>>>> +                Elf_Dyn __user *dyn;
>>>>>> +                Elf_Sword d_tag;
>>>>>>
>>>>>>                  params->dynamic_addr =
>>>>>>                      (phdr->p_vaddr - seg->p_vaddr) +
>>>>>> @@ -854,11 +854,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 == 0 ||
>>>>>> -                    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
>>>>>> +                    phdr->p_memsz % sizeof(Elf_Dyn) != 0)
>>>>>>                      goto dynamic_error;
>>>>>>
>>>>>> -                tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
>>>>>> -                dyn = (Elf32_Dyn __user *)params->dynamic_addr;
>>>>>> +                tmp = phdr->p_memsz / sizeof(Elf_Dyn);
>>>>>> +                dyn = (Elf_Dyn __user *)params->dynamic_addr;
>>>>>>                  if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
>>>>>>                      d_tag != 0)
>>>>>>                      goto dynamic_error;
>>>>>> @@ -927,8 +927,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 = ULONG_MAX, top = 0, maddr = 0;
>>>>>>      int loop, ret;
>>>>>>
>>>>>> @@ -1011,8 +1011,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_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;
>>>>>>
>>>>>> diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
>>>>>> index 3bea95a1af537..e533f45131945 100644
>>>>>> --- a/include/linux/elf-fdpic.h
>>>>>> +++ b/include/linux/elf-fdpic.h
>>>>>> @@ -10,13 +10,25 @@
>>>>>>
>>>>>>  #include <uapi/linux/elf-fdpic.h>
>>>>>>
>>>>>> +#if ELF_CLASS == 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 4fcc6cfebe185..ec23f08711292 100644
>>>>>> --- a/include/uapi/linux/elf-fdpic.h
>>>>>> +++ b/include/uapi/linux/elf-fdpic.h
>>>>>> @@ -32,4 +32,19 @@ struct elf32_fdpic_loadmap {
>>>>>>
>>>>>>  #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
>>>>>>
>>>>>> +/* 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 */
>>>>>