+++ /dev/null
-From 003abdd5f1a8f9b0e54ded266150d4b13c26a1aa Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 1 Sep 2025 20:53:50 +0700
-Subject: binfmt_elf: preserve original ELF e_flags for core dumps
-
-From: Svetlana Parfenova <svetlana.parfenova@syntacore.com>
-
-[ Upstream commit 8c94db0ae97c72c253a615f990bd466b456e94f6 ]
-
-Some architectures, such as RISC-V, use the ELF e_flags field to encode
-ABI-specific information (e.g., ISA extensions, fpu support). Debuggers
-like GDB rely on these flags in core dumps to correctly interpret
-optional register sets. If the flags are missing or incorrect, GDB may
-warn and ignore valid data, for example:
-
- warning: Unexpected size of section '.reg2/213' in core file.
-
-This can prevent access to fpu or other architecture-specific registers
-even when they were dumped.
-
-Save the e_flags field during ELF binary loading (in load_elf_binary())
-into the mm_struct, and later retrieve it during core dump generation
-(in fill_note_info()). Kconfig option CONFIG_ARCH_HAS_ELF_CORE_EFLAGS
-is introduced for architectures that require this behaviour.
-
-Signed-off-by: Svetlana Parfenova <svetlana.parfenova@syntacore.com>
-Link: https://lore.kernel.org/r/20250901135350.619485-1-svetlana.parfenova@syntacore.com
-Signed-off-by: Kees Cook <kees@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/riscv/Kconfig | 1 +
- fs/Kconfig.binfmt | 9 +++++++++
- fs/binfmt_elf.c | 40 ++++++++++++++++++++++++++++++++++------
- include/linux/mm_types.h | 5 +++++
- 4 files changed, 49 insertions(+), 6 deletions(-)
-
-diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
-index 51dcd8eaa2435..74db054aa1b8b 100644
---- a/arch/riscv/Kconfig
-+++ b/arch/riscv/Kconfig
-@@ -28,6 +28,7 @@ config RISCV
- select ARCH_HAS_DEBUG_VIRTUAL if MMU
- select ARCH_HAS_DEBUG_VM_PGTABLE
- select ARCH_HAS_DEBUG_WX
-+ select ARCH_HAS_ELF_CORE_EFLAGS
- select ARCH_HAS_FAST_MULTIPLIER
- select ARCH_HAS_FORTIFY_SOURCE
- select ARCH_HAS_GCOV_PROFILE_ALL
-diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
-index bd2f530e57408..1949e25c7741b 100644
---- a/fs/Kconfig.binfmt
-+++ b/fs/Kconfig.binfmt
-@@ -184,4 +184,13 @@ config EXEC_KUNIT_TEST
- This builds the exec KUnit tests, which tests boundary conditions
- of various aspects of the exec internals.
-
-+config ARCH_HAS_ELF_CORE_EFLAGS
-+ bool
-+ depends on BINFMT_ELF && ELF_CORE
-+ default n
-+ help
-+ Select this option if the architecture makes use of the e_flags
-+ field in the ELF header to store ABI or other architecture-specific
-+ information that should be preserved in core dumps.
-+
- endmenu
-diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
-index 264fba0d44bdf..c126e3d0e7018 100644
---- a/fs/binfmt_elf.c
-+++ b/fs/binfmt_elf.c
-@@ -103,6 +103,21 @@ static struct linux_binfmt elf_format = {
-
- #define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE))
-
-+static inline void elf_coredump_set_mm_eflags(struct mm_struct *mm, u32 flags)
-+{
-+#ifdef CONFIG_ARCH_HAS_ELF_CORE_EFLAGS
-+ mm->saved_e_flags = flags;
-+#endif
-+}
-+
-+static inline u32 elf_coredump_get_mm_eflags(struct mm_struct *mm, u32 flags)
-+{
-+#ifdef CONFIG_ARCH_HAS_ELF_CORE_EFLAGS
-+ flags = mm->saved_e_flags;
-+#endif
-+ return flags;
-+}
-+
- /*
- * We need to explicitly zero any trailing portion of the page that follows
- * p_filesz when it ends before the page ends (e.g. bss), otherwise this
-@@ -1290,6 +1305,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
- mm->end_data = end_data;
- mm->start_stack = bprm->p;
-
-+ elf_coredump_set_mm_eflags(mm, elf_ex->e_flags);
-+
- /**
- * DOC: "brk" handling
- *
-@@ -1804,6 +1821,8 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
- struct elf_thread_core_info *t;
- struct elf_prpsinfo *psinfo;
- struct core_thread *ct;
-+ u16 machine;
-+ u32 flags;
-
- psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
- if (!psinfo)
-@@ -1831,17 +1850,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
- return 0;
- }
-
-- /*
-- * Initialize the ELF file header.
-- */
-- fill_elf_header(elf, phdrs,
-- view->e_machine, view->e_flags);
-+ machine = view->e_machine;
-+ flags = view->e_flags;
- #else
- view = NULL;
- info->thread_notes = 2;
-- fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS);
-+ machine = ELF_ARCH;
-+ flags = ELF_CORE_EFLAGS;
- #endif
-
-+ /*
-+ * Override ELF e_flags with value taken from process,
-+ * if arch needs that.
-+ */
-+ flags = elf_coredump_get_mm_eflags(dump_task->mm, flags);
-+
-+ /*
-+ * Initialize the ELF file header.
-+ */
-+ fill_elf_header(elf, phdrs, machine, flags);
-+
- /*
- * Allocate a structure for each thread.
- */
-diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
-index a643fae8a3494..7f625c35128be 100644
---- a/include/linux/mm_types.h
-+++ b/include/linux/mm_types.h
-@@ -1107,6 +1107,11 @@ struct mm_struct {
-
- unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
-
-+#ifdef CONFIG_ARCH_HAS_ELF_CORE_EFLAGS
-+ /* the ABI-related flags from the ELF header. Used for core dump */
-+ unsigned long saved_e_flags;
-+#endif
-+
- struct percpu_counter rss_stat[NR_MM_COUNTERS];
-
- struct linux_binfmt *binfmt;
---
-2.51.0
-