linux-riscv.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Fix binfmt_flat loader for RISC-V
@ 2021-04-07 11:56 Damien Le Moal
  2021-04-07 11:56 ` [PATCH 1/2] binfmt_flat: allow not offsetting data start Damien Le Moal
  2021-04-07 11:56 ` [PATCH 2/2] riscv: introduce asm/flat.h Damien Le Moal
  0 siblings, 2 replies; 4+ messages in thread
From: Damien Le Moal @ 2021-04-07 11:56 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Alexander Viro, linux-kernel
  Cc: Max Filippov, Greg Ungerer, Anup Patel, Christoph Hellwig

RISC-V NOMMU flat binaries cannot tolerate a gap between the text and
data section as the toolchain fully resolve at compile time the PC
relative global pointer (__global_pointer$ value loaded in gp register).
Without a relocation entry provided, the flat bin loader cannot fix the
value if a gap is introduced and executables fail to run.

This series fixes this problem by allowing an architecture to request
the flat loader to suppress the gap between the text and data sections.
The first patch fixes binfmt_flat flat_load_file(). The second patch
adds the asm/flat.h file to riscv arch to request the gap suppression
using the newly introduced macro FLAT_TEXT_DATA_NO_GAP.

These patches do not change the binfmt_flat loader behavior for other
architectures.

Damien Le Moal (2):
  binfmt_flat: allow not offsetting data start
  riscv: introduce asm/flat.h

 arch/riscv/include/asm/Kbuild |  1 -
 arch/riscv/include/asm/flat.h | 29 +++++++++++++++++++++++++++++
 fs/binfmt_flat.c              | 25 +++++++++++++++++++------
 3 files changed, 48 insertions(+), 7 deletions(-)
 create mode 100644 arch/riscv/include/asm/flat.h

-- 
2.30.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] binfmt_flat: allow not offsetting data start
  2021-04-07 11:56 [PATCH 0/2] Fix binfmt_flat loader for RISC-V Damien Le Moal
@ 2021-04-07 11:56 ` Damien Le Moal
  2021-04-07 14:13   ` Christoph Hellwig
  2021-04-07 11:56 ` [PATCH 2/2] riscv: introduce asm/flat.h Damien Le Moal
  1 sibling, 1 reply; 4+ messages in thread
From: Damien Le Moal @ 2021-04-07 11:56 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Alexander Viro, linux-kernel
  Cc: Max Filippov, Greg Ungerer, Anup Patel, Christoph Hellwig

Commit 2217b9826246 ("binfmt_flat: revert "binfmt_flat: don't offset
the data start"") restored offsetting the start of the data section by
a number of words defined by MAX_SHARED_LIBS. As a result, since
MAX_SHARED_LIBS is never 0, a gap between the text and data sections
always exist. For architecture which cannot support a such gap between
the text and data sections (e.g. riscv nommu), flat binary programs
cannot be executed.

To allow an architecture to request contiguous text and data sections,
introduce the macro FLAT_TEXT_DATA_NO_GAP which can be defined by the
architecture in its asm/flat.h file. With this change, the macro
DATA_GAP_WORDS is conditionally defined in binfmt_flat.c to
MAX_SHARED_LIBS for architectures tolerating the gap
(FLAT_TEXT_DATA_NO_GAP undefined case) and to 0 when
FLAT_TEXT_DATA_NO_GAP is defined. DATA_GAP_WORDS is used in
load_flat_file() to calculate the data section length and start
position.

The definition of FLAT_TEXT_DATA_NO_GAP by an architecture also
prevents the use of the separate text/data load case (when
FLAT_FLAG_RAM and FLAT_FLAG_GZIP are not set with NOMMU kernels).

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 fs/binfmt_flat.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index b9c658e0548e..2bfa05ac5cb4 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -74,6 +74,12 @@
 #define	MAX_SHARED_LIBS			(1)
 #endif
 
+#ifdef FLAT_TEXT_DATA_NO_GAP
+#define DATA_GAP_WORDS			(0)
+#else
+#define DATA_GAP_WORDS			(MAX_SHARED_LIBS)
+#endif
+
 struct lib_info {
 	struct {
 		unsigned long start_code;		/* Start of text segment */
@@ -437,7 +443,6 @@ static int load_flat_file(struct linux_binprm *bprm,
 	__be32 __user *reloc;
 	u32 __user *rp;
 	int i, rev, relocs;
-	loff_t fpos;
 	unsigned long start_code, end_code;
 	ssize_t result;
 	int ret;
@@ -560,6 +565,9 @@ static int load_flat_file(struct linux_binprm *bprm,
 	 * it all together.
 	 */
 	if (!IS_ENABLED(CONFIG_MMU) && !(flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))) {
+#ifndef FLAT_TEXT_DATA_NO_GAP
+		loff_t fpos;
+
 		/*
 		 * this should give us a ROM ptr,  but if it doesn't we don't
 		 * really care
@@ -576,7 +584,7 @@ static int load_flat_file(struct linux_binprm *bprm,
 			goto err;
 		}
 
-		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
+		len = data_len + extra + DATA_GAP_WORDS * sizeof(unsigned long);
 		len = PAGE_ALIGN(len);
 		realdatastart = vm_mmap(NULL, 0, len,
 			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
@@ -591,7 +599,7 @@ static int load_flat_file(struct linux_binprm *bprm,
 			goto err;
 		}
 		datapos = ALIGN(realdatastart +
-				MAX_SHARED_LIBS * sizeof(unsigned long),
+				DATA_GAP_WORDS * sizeof(unsigned long),
 				FLAT_DATA_ALIGN);
 
 		pr_debug("Allocated data+bss+stack (%u bytes): %lx\n",
@@ -620,9 +628,14 @@ static int load_flat_file(struct linux_binprm *bprm,
 			(datapos + (ntohl(hdr->reloc_start) - text_len));
 		memp = realdatastart;
 		memp_size = len;
+#else
+		pr_err("Separate text/data loading not supported\n");
+		ret = -ENOEXEC;
+		goto err;
+#endif /* FLAT_TEXT_DATA_NO_GAP */
 	} else {
 
-		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
+		len = text_len + data_len + extra + DATA_GAP_WORDS * sizeof(u32);
 		len = PAGE_ALIGN(len);
 		textpos = vm_mmap(NULL, 0, len,
 			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
@@ -638,7 +651,7 @@ static int load_flat_file(struct linux_binprm *bprm,
 
 		realdatastart = textpos + ntohl(hdr->data_start);
 		datapos = ALIGN(realdatastart +
-				MAX_SHARED_LIBS * sizeof(u32),
+				DATA_GAP_WORDS * sizeof(u32),
 				FLAT_DATA_ALIGN);
 
 		reloc = (__be32 __user *)
@@ -714,7 +727,7 @@ static int load_flat_file(struct linux_binprm *bprm,
 			ret = result;
 			pr_err("Unable to read code+data+bss, errno %d\n", ret);
 			vm_munmap(textpos, text_len + data_len + extra +
-				MAX_SHARED_LIBS * sizeof(u32));
+				  DATA_GAP_WORDS * sizeof(u32));
 			goto err;
 		}
 	}
-- 
2.30.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] riscv: introduce asm/flat.h
  2021-04-07 11:56 [PATCH 0/2] Fix binfmt_flat loader for RISC-V Damien Le Moal
  2021-04-07 11:56 ` [PATCH 1/2] binfmt_flat: allow not offsetting data start Damien Le Moal
@ 2021-04-07 11:56 ` Damien Le Moal
  1 sibling, 0 replies; 4+ messages in thread
From: Damien Le Moal @ 2021-04-07 11:56 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Alexander Viro, linux-kernel
  Cc: Max Filippov, Greg Ungerer, Anup Patel, Christoph Hellwig

uclibc/gcc combined with elf2flt riscv linker file fully resolve the
PC relative __global_pointer$ value at compile time and do not generate
a relocation entry to set a runtime gp value. As a result, if the
flatbin loader introduces a gap between the text and data sections, the
gp value becomes incorrect and prevent correct execution of a flatbin
executable. Avoid this problem by introducing the file asm/flat.h
and defining the macro FLAT_TEXT_DATA_NO_GAP to indicate that the text
and data sections must be loaded at contiguous addresses.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/include/asm/Kbuild |  1 -
 arch/riscv/include/asm/flat.h | 29 +++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/flat.h

diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 445ccc97305a..a8b54a3f4c2b 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 generic-y += early_ioremap.h
 generic-y += extable.h
-generic-y += flat.h
 generic-y += kvm_para.h
 generic-y += user.h
 generic-y += vmlinux.lds.h
diff --git a/arch/riscv/include/asm/flat.h b/arch/riscv/include/asm/flat.h
new file mode 100644
index 000000000000..43bccf090fd1
--- /dev/null
+++ b/arch/riscv/include/asm/flat.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_FLAT_H
+#define _ASM_RISCV_FLAT_H
+
+#include <asm/unaligned.h>
+
+static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
+					u32 *addr)
+{
+	*addr = get_unaligned((__force u32 *)rp);
+	return 0;
+}
+
+static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
+{
+	put_unaligned(addr, (__force u32 *)rp);
+	return 0;
+}
+
+/*
+ * uclibc/gcc fully resolve the PC relative __global_pointer value
+ * at compile time and do not generate a relocation entry to set a
+ * runtime gp value. As a result, the flatbin loader must not introduce
+ * a gap between the text and data sections and keep them contiguous to
+ * avoid invalid address accesses.
+ */
+#define FLAT_TEXT_DATA_NO_GAP	(1)
+
+#endif /* _ASM_RISCV_FLAT_H */
-- 
2.30.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] binfmt_flat: allow not offsetting data start
  2021-04-07 11:56 ` [PATCH 1/2] binfmt_flat: allow not offsetting data start Damien Le Moal
@ 2021-04-07 14:13   ` Christoph Hellwig
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2021-04-07 14:13 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Alexander Viro, linux-kernel,
	Max Filippov, Greg Ungerer, Anup Patel, Christoph Hellwig

On Wed, Apr 07, 2021 at 08:56:37PM +0900, Damien Le Moal wrote:
> Commit 2217b9826246 ("binfmt_flat: revert "binfmt_flat: don't offset
> the data start"") restored offsetting the start of the data section by
> a number of words defined by MAX_SHARED_LIBS. As a result, since
> MAX_SHARED_LIBS is never 0, a gap between the text and data sections
> always exist. For architecture which cannot support a such gap between
> the text and data sections (e.g. riscv nommu), flat binary programs
> cannot be executed.
> 
> To allow an architecture to request contiguous text and data sections,
> introduce the macro FLAT_TEXT_DATA_NO_GAP which can be defined by the
> architecture in its asm/flat.h file. With this change, the macro
> DATA_GAP_WORDS is conditionally defined in binfmt_flat.c to
> MAX_SHARED_LIBS for architectures tolerating the gap
> (FLAT_TEXT_DATA_NO_GAP undefined case) and to 0 when
> FLAT_TEXT_DATA_NO_GAP is defined. DATA_GAP_WORDS is used in
> load_flat_file() to calculate the data section length and start
> position.
> 
> The definition of FLAT_TEXT_DATA_NO_GAP by an architecture also
> prevents the use of the separate text/data load case (when
> FLAT_FLAG_RAM and FLAT_FLAG_GZIP are not set with NOMMU kernels).

Please make this a CONFIG_* option selected by the architecture,
which also allows to use IS_ENABLED() to error out early for
your check.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-04-07 14:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-07 11:56 [PATCH 0/2] Fix binfmt_flat loader for RISC-V Damien Le Moal
2021-04-07 11:56 ` [PATCH 1/2] binfmt_flat: allow not offsetting data start Damien Le Moal
2021-04-07 14:13   ` Christoph Hellwig
2021-04-07 11:56 ` [PATCH 2/2] riscv: introduce asm/flat.h Damien Le Moal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).