execve updates for v6.18-rc1

- binfmt_elf: preserve original ELF e_flags for core dumps (Svetlana
   Parfenova)
 
 - exec: Fix incorrect type for ret (Xichao Zhao)
 
 - binfmt_elf: Replace offsetof() with struct_size() in fill_note_info()
   (Xichao Zhao)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCaNrYLAAKCRA2KwveOeQk
 u3hPAQCuJOg6CmTkv/lwDuI6aF5Q/UbEzhaHWnGqQOrxt3MVOQD/aIt49a1/i2i8
 ZdcAAxCabDwcZL51RcQCcihENVVI2As=
 =oRia
 -----END PGP SIGNATURE-----

Merge tag 'execve-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull execve updates from Kees Cook:

 - binfmt_elf: preserve original ELF e_flags for core dumps (Svetlana
   Parfenova)

 - exec: Fix incorrect type for ret (Xichao Zhao)

 - binfmt_elf: Replace offsetof() with struct_size() in fill_note_info()
   (Xichao Zhao)

* tag 'execve-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  binfmt_elf: preserve original ELF e_flags for core dumps
  binfmt_elf: Replace offsetof() with struct_size() in fill_note_info()
  exec: Fix incorrect type for ret
This commit is contained in:
Linus Torvalds 2025-09-29 17:19:35 -07:00
commit 50157eaa0c
5 changed files with 53 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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,30 +1850,37 @@ 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.
*/
info->thread = kzalloc(offsetof(struct elf_thread_core_info,
notes[info->thread_notes]),
GFP_KERNEL);
info->thread = kzalloc(struct_size(info->thread, notes, info->thread_notes),
GFP_KERNEL);
if (unlikely(!info->thread))
return 0;
info->thread->task = dump_task;
for (ct = dump_task->signal->core_state->dumper.next; ct; ct = ct->next) {
t = kzalloc(offsetof(struct elf_thread_core_info,
notes[info->thread_notes]),
t = kzalloc(struct_size(t, notes, info->thread_notes),
GFP_KERNEL);
if (unlikely(!t))
return 0;

View File

@ -599,7 +599,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
unsigned long stack_top,
int executable_stack)
{
unsigned long ret;
int ret;
unsigned long stack_shift;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma = bprm->vma;

View File

@ -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;