2019-06-13 16:40:04

by Christoph Hellwig

[permalink] [raw]
Subject: binfmt_flat cleanups and RISC-V support v2

Hi Greg,

below is a larger stash of cleanups for the binfmt_misc code,
preparing for the last patch that now trivially adds RISC-V
support, which will be used for the RISC-V nommu series I am
about to post.

Changes since v2:
- fix the handling of old format flags
- don't pass arguments on stack for RISC-V
- small cleanups for flat_v2_reloc_t


2019-06-13 16:40:30

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 09/17] binfmt_flat: use fixed size type for the on-disk format

So far binfmt_flat has only been supported on 32-bit platforms, so the
variable size of the fields didn't matter. But the upcoming RISC-V
nommu port supports 64-bit CPUs, and we now have a conflict between
the elf2flt creation tool that always uses 32-bit fields and the kernel
that uses (unsigned) long field. Switch to the userspace view as the
rest of the binfmt_flat format is completely architecture neutral,
and binfmt_flat isn't the right binary format for huge executables to
start with.

While we're at it also ensure these fields are using __be types as
they big endian and are byte swapped when loaded.

Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Vladimir Murzin <[email protected]>
---
include/linux/flat.h | 44 ++++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/include/linux/flat.h b/include/linux/flat.h
index 19c586b74b99..d586bb6e64a7 100644
--- a/include/linux/flat.h
+++ b/include/linux/flat.h
@@ -24,26 +24,26 @@
*/

struct flat_hdr {
- char magic[4];
- unsigned long rev; /* version (as above) */
- unsigned long entry; /* Offset of first executable instruction
- with text segment from beginning of file */
- unsigned long data_start; /* Offset of data segment from beginning of
- file */
- unsigned long data_end; /* Offset of end of data segment
- from beginning of file */
- unsigned long bss_end; /* Offset of end of bss segment from beginning
- of file */
+ char magic[4];
+ __be32 rev; /* version (as above) */
+ __be32 entry; /* Offset of first executable instruction
+ with text segment from beginning of file */
+ __be32 data_start; /* Offset of data segment from beginning of
+ file */
+ __be32 data_end; /* Offset of end of data segment from beginning
+ of file */
+ __be32 bss_end; /* Offset of end of bss segment from beginning
+ of file */

/* (It is assumed that data_end through bss_end forms the bss segment.) */

- unsigned long stack_size; /* Size of stack, in bytes */
- unsigned long reloc_start; /* Offset of relocation records from
- beginning of file */
- unsigned long reloc_count; /* Number of relocation records */
- unsigned long flags;
- unsigned long build_date; /* When the program/library was built */
- unsigned long filler[5]; /* Reservered, set to zero */
+ __be32 stack_size; /* Size of stack, in bytes */
+ __be32 reloc_start; /* Offset of relocation records from beginning of
+ file */
+ __be32 reloc_count; /* Number of relocation records */
+ __be32 flags;
+ __be32 build_date; /* When the program/library was built */
+ __u32 filler[5]; /* Reservered, set to zero */
};

#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */
@@ -67,15 +67,15 @@ struct flat_hdr {
#define OLD_FLAT_RELOC_TYPE_BSS 2

typedef union {
- unsigned long value;
+ u32 value;
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD) || \
(defined(mc68000) && !defined(CONFIG_COLDFIRE))
- signed long offset : 30;
- unsigned long type : 2;
+ s32 offset : 30;
+ u32 type : 2;
# elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned long type : 2;
- signed long offset : 30;
+ u32 type : 2;
+ s32 offset : 30;
# else
# error "Unknown bitfield order for flat files."
# endif
--
2.20.1

2019-06-13 16:40:51

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 04/17] binfmt_flat: remove flat_old_ram_flag

Instead add a Kconfig variable that only h8300 selects.

Signed-off-by: Christoph Hellwig <[email protected]>
---
arch/arm/include/asm/flat.h | 1 -
arch/c6x/include/asm/flat.h | 1 -
arch/h8300/Kconfig | 1 +
arch/h8300/include/asm/flat.h | 1 -
arch/m68k/include/asm/flat.h | 1 -
arch/microblaze/include/asm/flat.h | 1 -
arch/sh/include/asm/flat.h | 1 -
arch/xtensa/include/asm/flat.h | 1 -
fs/Kconfig.binfmt | 3 +++
fs/binfmt_flat.c | 3 ++-
10 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h
index a185fe023b60..acf162111ee2 100644
--- a/arch/arm/include/asm/flat.h
+++ b/arch/arm/include/asm/flat.h
@@ -9,7 +9,6 @@
#include <linux/uaccess.h>

#define flat_argvp_envp_on_stack() 1
-#define flat_old_ram_flag(flags) (flags)

static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr, u32 *persistent)
diff --git a/arch/c6x/include/asm/flat.h b/arch/c6x/include/asm/flat.h
index c4d703b454c6..353e4d06e8c0 100644
--- a/arch/c6x/include/asm/flat.h
+++ b/arch/c6x/include/asm/flat.h
@@ -5,7 +5,6 @@
#include <asm/unaligned.h>

#define flat_argvp_envp_on_stack() 0
-#define flat_old_ram_flag(flags) (flags)
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr, u32 *persistent)
{
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index ecfc4b4b6373..d30e8727b02d 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -2,6 +2,7 @@
config H8300
def_bool y
select ARCH_32BIT_OFF_T
+ select BINFMT_FLAT_OLD_ALWAYS_RAM
select GENERIC_ATOMIC64
select HAVE_UID16
select VIRT_TO_BUS
diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h
index 7ef7eefded3d..14cc928d5478 100644
--- a/arch/h8300/include/asm/flat.h
+++ b/arch/h8300/include/asm/flat.h
@@ -9,7 +9,6 @@
#include <asm/unaligned.h>

#define flat_argvp_envp_on_stack() 1
-#define flat_old_ram_flag(flags) 1

/*
* on the H8 a couple of the relocations have an instruction in the
diff --git a/arch/m68k/include/asm/flat.h b/arch/m68k/include/asm/flat.h
index 217fa89c8e34..7b1fb5c2809e 100644
--- a/arch/m68k/include/asm/flat.h
+++ b/arch/m68k/include/asm/flat.h
@@ -9,7 +9,6 @@
#include <linux/uaccess.h>

#define flat_argvp_envp_on_stack() 1
-#define flat_old_ram_flag(flags) (flags)
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr, u32 *persistent)
{
diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h
index 846084fa7f04..1cd8d7f4cf12 100644
--- a/arch/microblaze/include/asm/flat.h
+++ b/arch/microblaze/include/asm/flat.h
@@ -14,7 +14,6 @@
#include <asm/unaligned.h>

#define flat_argvp_envp_on_stack() 0
-#define flat_old_ram_flag(flags) (flags)

/*
* Microblaze works a little differently from other arches, because
diff --git a/arch/sh/include/asm/flat.h b/arch/sh/include/asm/flat.h
index 0d520b4cc5ea..015678d7b771 100644
--- a/arch/sh/include/asm/flat.h
+++ b/arch/sh/include/asm/flat.h
@@ -12,7 +12,6 @@
#include <asm/unaligned.h>

#define flat_argvp_envp_on_stack() 0
-#define flat_old_ram_flag(flags) (flags)
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr, u32 *persistent)
{
diff --git a/arch/xtensa/include/asm/flat.h b/arch/xtensa/include/asm/flat.h
index a1d88aa3ef8a..b215c1e66958 100644
--- a/arch/xtensa/include/asm/flat.h
+++ b/arch/xtensa/include/asm/flat.h
@@ -5,7 +5,6 @@
#include <asm/unaligned.h>

#define flat_argvp_envp_on_stack() 0
-#define flat_old_ram_flag(flags) (flags)
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr, u32 *persistent)
{
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index f87ddd1b6d72..5658e12ad944 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -97,6 +97,9 @@ config BINFMT_FLAT
help
Support uClinux FLAT format binaries.

+config BINFMT_FLAT_OLD_ALWAYS_RAM
+ bool
+
config BINFMT_ZFLAT
bool "Enable ZFLAT support"
depends on BINFMT_FLAT
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index c0e4535dc1ec..3e7f4a6cffa2 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -488,7 +488,8 @@ static int load_flat_file(struct linux_binprm *bprm,
* fix up the flags for the older format, there were all kinds
* of endian hacks, this only works for the simple cases
*/
- if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
+ if (rev == OLD_FLAT_VERSION &&
+ (flags || IS_ENABLED(CONFIG_BINFMT_FLAT_OLD_ALWAYS_RAM)))
flags = FLAT_FLAG_RAM;

#ifndef CONFIG_BINFMT_ZFLAT
--
2.20.1

2019-06-13 16:41:06

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 02/17] binfmt_flat: remove flat_set_persistent

This helper is a no-op on all architectures, remove it.

Signed-off-by: Christoph Hellwig <[email protected]>
Tested-by: Vladimir Murzin <[email protected]>
Reviewed-by: Vladimir Murzin <[email protected]>
---
arch/arm/include/asm/flat.h | 1 -
arch/c6x/include/asm/flat.h | 1 -
arch/h8300/include/asm/flat.h | 1 -
arch/m68k/include/asm/flat.h | 5 -----
arch/microblaze/include/asm/flat.h | 1 -
arch/sh/include/asm/flat.h | 1 -
arch/xtensa/include/asm/flat.h | 1 -
fs/binfmt_flat.c | 2 --
8 files changed, 13 deletions(-)

diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h
index 10cce9ecf151..576241d74704 100644
--- a/arch/arm/include/asm/flat.h
+++ b/arch/arm/include/asm/flat.h
@@ -31,6 +31,5 @@ static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
}

#define flat_get_relocate_addr(rel) (rel)
-#define flat_set_persistent(relval, p) 0

#endif /* __ARM_FLAT_H__ */
diff --git a/arch/c6x/include/asm/flat.h b/arch/c6x/include/asm/flat.h
index ecc6aea6606c..ac87368efad1 100644
--- a/arch/c6x/include/asm/flat.h
+++ b/arch/c6x/include/asm/flat.h
@@ -18,6 +18,5 @@ static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
return 0;
}
#define flat_get_relocate_addr(rel) (rel)
-#define flat_set_persistent(relval, p) 0

#endif /* __ASM_C6X_FLAT_H */
diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h
index dcc7775115dd..7ef7eefded3d 100644
--- a/arch/h8300/include/asm/flat.h
+++ b/arch/h8300/include/asm/flat.h
@@ -10,7 +10,6 @@

#define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) 1
-#define flat_set_persistent(relval, p) 0

/*
* on the H8 a couple of the relocations have an instruction in the
diff --git a/arch/m68k/include/asm/flat.h b/arch/m68k/include/asm/flat.h
index a631caf5e18f..955617bb937b 100644
--- a/arch/m68k/include/asm/flat.h
+++ b/arch/m68k/include/asm/flat.h
@@ -30,11 +30,6 @@ static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
}
#define flat_get_relocate_addr(rel) (rel)

-static inline int flat_set_persistent(u32 relval, u32 *persistent)
-{
- return 0;
-}
-
#define FLAT_PLAT_INIT(regs) \
do { \
if (current->mm) \
diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h
index 34be5ed011be..846084fa7f04 100644
--- a/arch/microblaze/include/asm/flat.h
+++ b/arch/microblaze/include/asm/flat.h
@@ -15,7 +15,6 @@

#define flat_argvp_envp_on_stack() 0
#define flat_old_ram_flag(flags) (flags)
-#define flat_set_persistent(relval, p) 0

/*
* Microblaze works a little differently from other arches, because
diff --git a/arch/sh/include/asm/flat.h b/arch/sh/include/asm/flat.h
index 8f2929b32f2e..6f3b18679a98 100644
--- a/arch/sh/include/asm/flat.h
+++ b/arch/sh/include/asm/flat.h
@@ -25,7 +25,6 @@ static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
return 0;
}
#define flat_get_relocate_addr(rel) (rel)
-#define flat_set_persistent(relval, p) ({ (void)p; 0; })

#define FLAT_PLAT_INIT(_r) \
do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \
diff --git a/arch/xtensa/include/asm/flat.h b/arch/xtensa/include/asm/flat.h
index 6ee5a35eb0ec..b1bc0d9a8d4e 100644
--- a/arch/xtensa/include/asm/flat.h
+++ b/arch/xtensa/include/asm/flat.h
@@ -18,6 +18,5 @@ static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
return 0;
}
#define flat_get_relocate_addr(rel) (rel)
-#define flat_set_persistent(relval, p) 0

#endif /* __ASM_XTENSA_FLAT_H */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index afddea583999..a4c0b245ab1f 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -787,8 +787,6 @@ static int load_flat_file(struct linux_binprm *bprm,
if (get_user(relval, reloc + i))
return -EFAULT;
relval = ntohl(relval);
- if (flat_set_persistent(relval, &persistent))
- continue;
addr = flat_get_relocate_addr(relval);
rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
if (rp == (u32 __user *)RELOC_FAILED) {
--
2.20.1

2019-06-13 23:39:59

by Greg Ungerer

[permalink] [raw]
Subject: Re: binfmt_flat cleanups and RISC-V support v2

Hi Christoph,

On 13/6/19 5:08 pm, Christoph Hellwig wrote:
> below is a larger stash of cleanups for the binfmt_misc code,
> preparing for the last patch that now trivially adds RISC-V
> support, which will be used for the RISC-V nommu series I am
> about to post.
>
> Changes since v2:
> - fix the handling of old format flags
> - don't pass arguments on stack for RISC-V
> - small cleanups for flat_v2_reloc_t

Thanks for doing this work. Tested and works for me on
m68k/Coldfire too.

I have pushed these onto the for-next branch of the
m68knommu git tree.

Regards
Greg