diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 09:29:23 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 09:29:23 -0800 |
commit | 591fd30eee47ed75d1296d619dd467414d0894e3 (patch) | |
tree | f3fd8b651b9143194c6a1480ba3f7ecaea84feae | |
parent | 054560e961a0ee4067fccfcfa943335e1aa48928 (diff) | |
parent | e565d89e4aa07e3f20ac5e8757b1da24b5878e69 (diff) |
Merge branch 'work.elf-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull ELF compat updates from Al Viro:
"Sanitizing ELF compat support, especially for triarch architectures:
- X32 handling cleaned up
- MIPS64 uses compat_binfmt_elf.c both for O32 and N32 now
- Kconfig side of things regularized
Eventually I hope to have compat_binfmt_elf.c killed, with both native
and compat built from fs/binfmt_elf.c, with -DELF_BITS={64,32} passed
by kbuild, but that's a separate story - not included here"
* 'work.elf-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
get rid of COMPAT_ELF_EXEC_PAGESIZE
compat_binfmt_elf: don't bother with undef of ELF_ARCH
Kconfig: regularize selection of CONFIG_BINFMT_ELF
mips compat: switch to compat_binfmt_elf.c
mips: don't bother with ELF_CORE_EFLAGS
mips compat: don't bother with ELF_ET_DYN_BASE
mips: KVM_GUEST makes no sense for 64bit builds...
mips: kill unused definitions in binfmt_elf[on]32.c
mips binfmt_elf*32.c: use elfcore-compat.h
x32: make X32, !IA32_EMULATION setups able to execute x32 binaries
[amd64] clean PRSTATUS_SIZE/SET_PR_FPVALID up properly
elf_prstatus: collect the common part (everything before pr_reg) into a struct
binfmt_elf: partially sanitize PRSTATUS_SIZE and SET_PR_FPVALID
-rw-r--r-- | arch/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm64/Kconfig | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/crash.c | 2 | ||||
-rw-r--r-- | arch/mips/Kconfig | 8 | ||||
-rw-r--r-- | arch/mips/include/asm/elf.h | 56 | ||||
-rw-r--r-- | arch/mips/include/asm/elfcore-compat.h | 29 | ||||
-rw-r--r-- | arch/mips/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/kernel/binfmt_elfn32.c | 113 | ||||
-rw-r--r-- | arch/mips/kernel/binfmt_elfo32.c | 116 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n64.S | 2 | ||||
-rw-r--r-- | arch/parisc/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-core.c | 6 | ||||
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 2 | ||||
-rw-r--r-- | arch/sparc/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/compat.h | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/elf.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/elfcore-compat.h | 31 | ||||
-rw-r--r-- | fs/Kconfig.binfmt | 2 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 21 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 22 | ||||
-rw-r--r-- | fs/compat_binfmt_elf.c | 7 | ||||
-rw-r--r-- | include/linux/elfcore-compat.h | 15 | ||||
-rw-r--r-- | include/linux/elfcore.h | 7 | ||||
-rw-r--r-- | kernel/kexec_core.c | 2 |
27 files changed, 129 insertions, 339 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 24862d15f3a3..b8bbfd3c66b8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1111,6 +1111,9 @@ config ARCH_SPLIT_ARG64 If a 32-bit architecture requires 64-bit arguments to be split into pairs of 32-bit arguments, select this option. +config ARCH_HAS_ELFCORE_COMPAT + bool + source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index f39568b28ec1..52bc8f6206b7 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1213,7 +1213,6 @@ config ARM64_TAGGED_ADDR_ABI menuconfig COMPAT bool "Kernel support for 32-bit EL0" depends on ARM64_4K_PAGES || EXPERT - select COMPAT_BINFMT_ELF if BINFMT_ELF select HAVE_UID16 select OLD_SIGSUSPEND3 select COMPAT_OLD_SIGACTION diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c index fec70d662d0c..4f47741005d2 100644 --- a/arch/ia64/kernel/crash.c +++ b/arch/ia64/kernel/crash.c @@ -43,7 +43,7 @@ crash_save_this_cpu(void) elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg); memset(prstatus, 0, sizeof(*prstatus)); - prstatus->pr_pid = current->pid; + prstatus->common.pr_pid = current->pid; ia64_dump_cpu_regs(dst); cfm = dst[43]; diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0a17bedf4f0d..f29ec95e3458 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -92,6 +92,7 @@ config MIPS select SET_FS select SYSCTL_EXCEPTION_TRACE select VIRT_TO_BUS + select ARCH_HAS_ELFCORE_COMPAT config MIPS_FIXUP_BIGPHYS_ADDR bool @@ -2182,7 +2183,7 @@ endchoice config KVM_GUEST bool "KVM Guest Kernel" depends on CPU_MIPS32_R2 - depends on BROKEN_ON_SMP + depends on !64BIT && BROKEN_ON_SMP help Select this option if building a guest kernel for KVM (Trap & Emulate) mode. @@ -3300,11 +3301,6 @@ config MIPS32_N32 If unsure, say N. -config BINFMT_ELF32 - bool - default y if MIPS32_O32 || MIPS32_N32 - select ELFCORE - menu "Power management options" config ARCH_HIBERNATION_POSSIBLE diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 71c7622025d1..dc8d2863752c 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -201,7 +201,6 @@ struct mips_elf_abiflags_v0 { uint32_t flags2; }; -#ifndef ELF_ARCH /* ELF register definitions */ #define ELF_NGREG 45 #define ELF_NFPREG 33 @@ -219,7 +218,7 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch elfo32_check_arch +#define elf_check_arch elf32_check_arch /* * These are used to set parameters in the core dumps. @@ -235,7 +234,8 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch elfn64_check_arch +#define elf_check_arch elf64_check_arch +#define compat_elf_check_arch elf32_check_arch /* * These are used to set parameters in the core dumps. @@ -257,8 +257,6 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); #endif #define ELF_ARCH EM_MIPS -#endif /* !defined(ELF_ARCH) */ - /* * In order to be sure that we don't attempt to execute an O32 binary which * requires 64 bit FP (FR=1) on a system which does not support it we refuse @@ -277,9 +275,9 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); #define vmcore_elf64_check_arch mips_elf_check_machine /* - * Return non-zero if HDR identifies an o32 ELF binary. + * Return non-zero if HDR identifies an o32 or n32 ELF binary. */ -#define elfo32_check_arch(hdr) \ +#define elf32_check_arch(hdr) \ ({ \ int __res = 1; \ struct elfhdr *__h = (hdr); \ @@ -288,21 +286,26 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); __res = 0; \ if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ __res = 0; \ - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ - __res = 0; \ - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ - __res = 0; \ - \ + if ((__h->e_flags & EF_MIPS_ABI2) != 0) { \ + if (!IS_ENABLED(CONFIG_MIPS32_N32) || \ + (__h->e_flags & EF_MIPS_ABI)) \ + __res = 0; \ + } else { \ + if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32)) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ + __res = 0; \ + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ + __res = 0; \ + } \ __res; \ }) /* * Return non-zero if HDR identifies an n64 ELF binary. */ -#define elfn64_check_arch(hdr) \ +#define elf64_check_arch(hdr) \ ({ \ int __res = 1; \ struct elfhdr *__h = (hdr); \ @@ -315,25 +318,6 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); __res; \ }) -/* - * Return non-zero if HDR identifies an n32 ELF binary. - */ -#define elfn32_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ - ((__h->e_flags & EF_MIPS_ABI) != 0)) \ - __res = 0; \ - \ - __res; \ -}) - struct mips_abi; extern struct mips_abi mips_abi; @@ -469,9 +453,7 @@ extern const char *__elf_base_platform; the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#ifndef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) -#endif /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ #define ARCH_DLINFO \ diff --git a/arch/mips/include/asm/elfcore-compat.h b/arch/mips/include/asm/elfcore-compat.h new file mode 100644 index 000000000000..2f0f0103c75b --- /dev/null +++ b/arch/mips/include/asm/elfcore-compat.h @@ -0,0 +1,29 @@ +#ifndef _ASM_MIPS_ELFCORE_COMPAT_H +#define _ASM_MIPS_ELFCORE_COMPAT_H + +/* + * On mips we have two 32bit ABIs - o32 and n32. The latter + * has bigger registers, so we use it for compat_elf_regset_t. + * The former uses o32_elf_prstatus and PRSTATUS_SIZE/SET_PR_FPVALID + * are used to choose the size and location of ->pr_fpvalid of + * the layout actually used. + */ +typedef elf_gregset_t compat_elf_gregset_t; + +struct o32_elf_prstatus +{ + struct compat_elf_prstatus_common common; + unsigned int pr_reg[ELF_NGREG]; + compat_int_t pr_fpvalid; +}; + +#define PRSTATUS_SIZE \ + (!test_thread_flag(TIF_32BIT_REGS) \ + ? sizeof(struct compat_elf_prstatus) \ + : sizeof(struct o32_elf_prstatus)) +#define SET_PR_FPVALID(S) \ + (*(!test_thread_flag(TIF_32BIT_REGS) \ + ? &(S)->pr_fpvalid \ + : &((struct o32_elf_prstatus *)(S))->pr_fpvalid) = 1) + +#endif diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 2a05b923f579..943eaeef73e9 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -80,8 +80,8 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-n64.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o -obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o -obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o signal_o32.o +obj-$(CONFIG_MIPS32_N32) += scall64-n32.o signal_n32.o +obj-$(CONFIG_MIPS32_O32) += scall64-o32.o signal_o32.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_PROC_FS) += proc.o diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c deleted file mode 100644 index c4441416e96b..000000000000 --- a/arch/mips/kernel/binfmt_elfn32.c +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for n32 Linux/MIPS ELF binaries. - * Author: Ralf Baechle (ralf@linux-mips.org) - * - * Copyright (C) 1999, 2001 Ralf Baechle - * Copyright (C) 1999, 2001 Silicon Graphics, Inc. - * - * Heavily inspired by the 32-bit Sparc compat code which is - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#define ELF_ARCH EM_MIPS -#define ELF_CLASS ELFCLASS32 -#ifdef __MIPSEB__ -#define ELF_DATA ELFDATA2MSB; -#else /* __MIPSEL__ */ -#define ELF_DATA ELFDATA2LSB; -#endif - -/* ELF register definitions */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned long elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch elfn32_check_arch - -#define TASK32_SIZE 0x7fff8000UL -#undef ELF_ET_DYN_BASE -#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) - -#include <asm/processor.h> -#include <linux/elfcore.h> -#include <linux/compat.h> -#include <linux/math64.h> - -#define elf_prstatus elf_prstatus32 -struct elf_prstatus32 -{ - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned int pr_sigpend; /* Set of pending signals */ - unsigned int pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct old_timeval32 pr_utime; /* User time */ - struct old_timeval32 pr_stime; /* System time */ - struct old_timeval32 pr_cutime;/* Cumulative user time */ - struct old_timeval32 pr_cstime;/* Cumulative system time */ - elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* True if math co-processor being used. */ -}; - -#define elf_prpsinfo elf_prpsinfo32 -struct elf_prpsinfo32 -{ - char pr_state; /* numeric process state */ - char pr_sname; /* char for pr_state */ - char pr_zomb; /* zombie */ - char pr_nice; /* nice val */ - unsigned int pr_flag; /* flags */ - __kernel_uid_t pr_uid; - __kernel_gid_t pr_gid; - pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* filename of executable */ - char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ -}; - -#define elf_caddr_t u32 -#define init_elf_binfmt init_elfn32_binfmt - -#define jiffies_to_timeval jiffies_to_old_timeval32 -static __inline__ void -jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) -{ - /* - * Convert jiffies to nanoseconds and separate with - * one divide. - */ - u64 nsec = (u64)jiffies * TICK_NSEC; - u32 rem; - value->tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem); - value->tv_usec = rem / NSEC_PER_USEC; -} - -#define ELF_CORE_EFLAGS EF_MIPS_ABI2 - -#undef TASK_SIZE -#define TASK_SIZE TASK_SIZE32 - -#undef ns_to_kernel_old_timeval -#define ns_to_kernel_old_timeval ns_to_old_timeval32 - -/* - * Some data types as stored in coredump. - */ -#define user_long_t compat_long_t -#define user_siginfo_t compat_siginfo_t -#define copy_siginfo_to_external copy_siginfo_to_external32 - -#include "../../../fs/binfmt_elf.c" diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c deleted file mode 100644 index 7b2a23f48c1a..000000000000 --- a/arch/mips/kernel/binfmt_elfo32.c +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for o32 Linux/MIPS ELF binaries. - * Author: Ralf Baechle (ralf@linux-mips.org) - * - * Copyright (C) 1999, 2001 Ralf Baechle - * Copyright (C) 1999, 2001 Silicon Graphics, Inc. - * - * Heavily inspired by the 32-bit Sparc compat code which is - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#define ELF_ARCH EM_MIPS -#define ELF_CLASS ELFCLASS32 -#ifdef __MIPSEB__ -#define ELF_DATA ELFDATA2MSB; -#else /* __MIPSEL__ */ -#define ELF_DATA ELFDATA2LSB; -#endif - -/* ELF register definitions */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned int elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch elfo32_check_arch - -#ifdef CONFIG_KVM_GUEST -#define TASK32_SIZE 0x3fff8000UL -#else -#define TASK32_SIZE 0x7fff8000UL -#endif -#undef ELF_ET_DYN_BASE -#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) - -#include <asm/processor.h> - -#include <linux/elfcore.h> -#include <linux/compat.h> -#include <linux/math64.h> - -#define elf_prstatus elf_prstatus32 -struct elf_prstatus32 -{ - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned int pr_sigpend; /* Set of pending signals */ - unsigned int pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct old_timeval32 pr_utime; /* User time */ - struct old_timeval32 pr_stime; /* System time */ - struct old_timeval32 pr_cutime;/* Cumulative user time */ - struct old_timeval32 pr_cstime;/* Cumulative system time */ - elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* True if math co-processor being used. */ -}; - -#define elf_prpsinfo elf_prpsinfo32 -struct elf_prpsinfo32 -{ - char pr_state; /* numeric process state */ - char pr_sname; /* char for pr_state */ - char pr_zomb; /* zombie */ - char pr_nice; /* nice val */ - unsigned int pr_flag; /* flags */ - __kernel_uid_t pr_uid; - __kernel_gid_t pr_gid; - pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* filename of executable */ - char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ -}; - -#define elf_caddr_t u32 -#define init_elf_binfmt init_elf32_binfmt - -#define jiffies_to_timeval jiffies_to_old_timeval32 -static inline void -jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) -{ - /* - * Convert jiffies to nanoseconds and separate with - * one divide. - */ - u64 nsec = (u64)jiffies * TICK_NSEC; - u32 rem; - value->tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem); - value->tv_usec = rem / NSEC_PER_USEC; -} - -#undef TASK_SIZE -#define TASK_SIZE TASK_SIZE32 - -#undef ns_to_kernel_old_timeval -#define ns_to_kernel_old_timeval ns_to_old_timeval32 - -/* - * Some data types as stored in coredump. - */ -#define user_long_t compat_long_t -#define user_siginfo_t compat_siginfo_t -#define copy_siginfo_to_external copy_siginfo_to_external32 - -#include "../../../fs/binfmt_elf.c" diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S index 23b2e2b1609c..5e9c497ce099 100644 --- a/arch/mips/kernel/scall64-n64.S +++ b/arch/mips/kernel/scall64-n64.S @@ -20,7 +20,7 @@ #include <asm/unistd.h> #include <asm/war.h> -#ifndef CONFIG_BINFMT_ELF32 +#ifndef CONFIG_MIPS32_COMPAT /* Neither O32 nor N32, so define handle_sys here */ #define handle_sys64 handle_sys #endif diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 278462186ac4..b09d6923f156 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -335,7 +335,6 @@ source "kernel/Kconfig.hz" config COMPAT def_bool y depends on 64BIT - select COMPAT_BINFMT_ELF if BINFMT_ELF config SYSVIPC_COMPAT def_bool y diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 107bb4319e0e..d26a89cd8908 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -282,7 +282,6 @@ config COMPAT bool "Enable support for 32bit binaries" depends on PPC64 default y if !CPU_LITTLE_ENDIAN - select COMPAT_BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION diff --git a/arch/powerpc/platforms/powernv/opal-core.c b/arch/powerpc/platforms/powernv/opal-core.c index 23571f0b555a..0d9ba70f7251 100644 --- a/arch/powerpc/platforms/powernv/opal-core.c +++ b/arch/powerpc/platforms/powernv/opal-core.c @@ -119,8 +119,8 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir, * As a PIR value could also be '0', add an offset of '100' * to every PIR to avoid misinterpretations in GDB. */ - prstatus->pr_pid = cpu_to_be32(100 + pir); - prstatus->pr_ppid = cpu_to_be32(1); + prstatus->common.pr_pid = cpu_to_be32(100 + pir); + prstatus->common.pr_ppid = cpu_to_be32(1); /* * Indicate SIGUSR1 for crash initiated from kernel. @@ -130,7 +130,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir, short sig; sig = kernel_initiated ? SIGUSR1 : SIGTERM; - prstatus->pr_cursig = cpu_to_be16(sig); + prstatus->common.pr_cursig = cpu_to_be16(sig); } } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index c72874f09741..73483614b66b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -426,7 +426,6 @@ config 64BIT config COMPAT def_bool y prompt "Kernel support for 31 bit emulation" - select COMPAT_BINFMT_ELF if BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION select HAVE_UID16 diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 205b2e2648aa..0e36dfc9ccd6 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -365,7 +365,7 @@ static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa) memcpy(&nt_prstatus.pr_reg.gprs, sa->gprs, sizeof(sa->gprs)); memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw)); memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs)); - nt_prstatus.pr_pid = cpu; + nt_prstatus.common.pr_pid = cpu; /* Prepare fpregset (floating point) note */ memset(&nt_fpregset, 0, sizeof(nt_fpregset)); memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc)); diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c9c34dc52b7d..1a2b5649d267 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -494,7 +494,6 @@ config COMPAT bool depends on SPARC64 default y - select COMPAT_BINFMT_ELF select HAVE_UID16 select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3d498caca1ea..31d94448b4e1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -32,6 +32,7 @@ config X86_64 select MODULES_USE_ELF_RELA select NEED_DMA_MAP_STATE select SWIOTLB + select ARCH_HAS_ELFCORE_COMPAT config FORCE_DYNAMIC_FTRACE def_bool y @@ -2860,7 +2861,6 @@ config IA32_EMULATION depends on X86_64 select ARCH_WANT_OLD_COMPAT_IPC select BINFMT_ELF - select COMPAT_BINFMT_ELF select COMPAT_OLD_SIGACTION help Include code to run legacy 32-bit programs under a diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index f145e3326c6d..be09c7eac89f 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -159,17 +159,6 @@ struct compat_shmid64_ds { compat_ulong_t __unused5; }; -/* - * The type of struct elf_prstatus.pr_reg in compatible core dumps. - */ -typedef struct user_regs_struct compat_elf_gregset_t; - -/* Full regset -- prstatus on x32, otherwise on ia32 */ -#define PRSTATUS_SIZE(S, R) (R != sizeof(S.pr_reg) ? 144 : 296) -#define SET_PR_FPVALID(S, V, R) \ - do { *(int *) (((void *) &((S)->pr_reg)) + R) = (V); } \ - while (0) - #ifdef CONFIG_X86_X32_ABI #define COMPAT_USE_64BIT_TIME \ (!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 66bdfe838d61..9224d40cdefe 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -364,7 +364,7 @@ do { \ #define COMPAT_ARCH_DLINFO \ if (exec->e_machine == EM_X86_64) \ ARCH_DLINFO_X32; \ -else \ +else if (IS_ENABLED(CONFIG_IA32_EMULATION)) \ ARCH_DLINFO_IA32 #define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) diff --git a/arch/x86/include/asm/elfcore-compat.h b/arch/x86/include/asm/elfcore-compat.h new file mode 100644 index 000000000000..f1b6c7a8d8fc --- /dev/null +++ b/arch/x86/include/asm/elfcore-compat.h @@ -0,0 +1,31 @@ +#ifndef _ASM_X86_ELFCORE_COMPAT_H +#define _ASM_X86_ELFCORE_COMPAT_H + +#include <asm/user32.h> + +/* + * On amd64 we have two 32bit ABIs - i386 and x32. The latter + * has bigger registers, so we use it for compat_elf_regset_t. + * The former uses i386_elf_prstatus and PRSTATUS_SIZE/SET_PR_FPVALID + * are used to choose the size and location of ->pr_fpvalid of + * the layout actually used. + */ +typedef struct user_regs_struct compat_elf_gregset_t; + +struct i386_elf_prstatus +{ + struct compat_elf_prstatus_common common; + struct user_regs_struct32 pr_reg; + compat_int_t pr_fpvalid; +}; + +#define PRSTATUS_SIZE \ + (user_64bit_mode(task_pt_regs(current)) \ + ? sizeof(struct compat_elf_prstatus) \ + : sizeof(struct i386_elf_prstatus)) +#define SET_PR_FPVALID(S) \ + (*(user_64bit_mode(task_pt_regs(current)) \ + ? &(S)->pr_fpvalid \ + : &((struct i386_elf_prstatus *)(S))->pr_fpvalid) = 1) + +#endif diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 647439c2c05a..c6f1c8c1934e 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -29,7 +29,7 @@ config BINFMT_ELF latest version). config COMPAT_BINFMT_ELF - bool + def_bool y depends on COMPAT && BINFMT_ELF select ELFCORE diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 950bc177238a..4c1550b13899 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1495,7 +1495,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type, * fill up all the fields in prstatus from the given task struct, except * registers which need to be filled up separately. */ -static void fill_prstatus(struct elf_prstatus *prstatus, +static void fill_prstatus(struct elf_prstatus_common *prstatus, struct task_struct *p, long signr) { prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; @@ -1717,11 +1717,11 @@ static void do_thread_regset_writeback(struct task_struct *task, } #ifndef PRSTATUS_SIZE -#define PRSTATUS_SIZE(S, R) sizeof(S) +#define PRSTATUS_SIZE sizeof(struct elf_prstatus) #endif #ifndef SET_PR_FPVALID -#define SET_PR_FPVALID(S, V, R) ((S)->pr_fpvalid = (V)) +#define SET_PR_FPVALID(S) ((S)->pr_fpvalid = 1) #endif static int fill_thread_core_info(struct elf_thread_core_info *t, @@ -1729,7 +1729,6 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, long signr, size_t *total) { unsigned int i; - int regset0_size; /* * NT_PRSTATUS is the one special case, because the regset data @@ -1737,14 +1736,12 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, * than being the whole note contents. We fill the reset in here. * We assume that regset 0 is NT_PRSTATUS. */ - fill_prstatus(&t->prstatus, t->task, signr); - regset0_size = regset_get(t->task, &view->regsets[0], + fill_prstatus(&t->prstatus.common, t->task, signr); + regset_get(t->task, &view->regsets[0], sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); - if (regset0_size < 0) - return 0; fill_note(&t->notes[0], "CORE", NT_PRSTATUS, - PRSTATUS_SIZE(t->prstatus, regset0_size), &t->prstatus); + PRSTATUS_SIZE, &t->prstatus); *total += notesize(&t->notes[0]); do_thread_regset_writeback(t->task, &view->regsets[0]); @@ -1772,7 +1769,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, continue; if (is_fpreg) - SET_PR_FPVALID(&t->prstatus, 1, regset0_size); + SET_PR_FPVALID(&t->prstatus); fill_note(&t->notes[i], is_fpreg ? "CORE" : "LINUX", note_type, ret, data); @@ -1961,7 +1958,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) struct task_struct *p = t->thread; t->num_notes = 0; - fill_prstatus(&t->prstatus, p, signr); + fill_prstatus(&t->prstatus.common, p, signr); elf_core_copy_task_regs(p, &t->prstatus.pr_reg); fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), @@ -2040,7 +2037,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, } /* now collect the dump for the current */ memset(info->prstatus, 0, sizeof(*info->prstatus)); - fill_prstatus(info->prstatus, current, siginfo->si_signo); + fill_prstatus(&info->prstatus->common, current, siginfo->si_signo); elf_core_copy_regs(&info->prstatus->pr_reg, regs); /* Set up header */ diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index be4062b8ba75..03d81a14bcbf 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1191,18 +1191,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, struct elf_prstatus_fdpic { - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned long pr_sigpend; /* Set of pending signals */ - unsigned long pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct __kernel_old_timeval pr_utime; /* User time */ - struct __kernel_old_timeval pr_stime; /* System time */ - struct __kernel_old_timeval pr_cutime; /* Cumulative user time */ - struct __kernel_old_timeval pr_cstime; /* Cumulative system time */ + struct elf_prstatus_common common; elf_gregset_t pr_reg; /* GP registers */ /* When using FDPIC, the loadmap addresses need to be communicated * to GDB in order for GDB to do the necessary relocations. The @@ -1301,7 +1290,7 @@ static inline void fill_note(struct memelfnote *note, const char *name, int type * fill up all the fields in prstatus from the given task struct, except * registers which need to be filled up separately. */ -static void fill_prstatus(struct elf_prstatus_fdpic *prstatus, +static void fill_prstatus(struct elf_prstatus_common *prstatus, struct task_struct *p, long signr) { prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; @@ -1332,9 +1321,6 @@ static void fill_prstatus(struct elf_prstatus_fdpic *prstatus, } prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime); prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime); - - prstatus->pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap; - prstatus->pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap; } static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, @@ -1405,7 +1391,9 @@ static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_ if (!t) return t; - fill_prstatus(&t->prstatus, p, signr); + fill_prstatus(&t->prstatus.common, p, signr); + t->prstatus.pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap; + t->prstatus.pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap; regset_get(p, &view->regsets[0], sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 2c557229696a..95e72d271b95 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -50,6 +50,7 @@ * which requires asm/elf.h to define compat_elf_gregset_t et al. */ #define elf_prstatus compat_elf_prstatus +#define elf_prstatus_common compat_elf_prstatus_common #define elf_prpsinfo compat_elf_prpsinfo #undef ns_to_kernel_old_timeval @@ -61,7 +62,6 @@ * differ from the native ones, or omitted when they match. */ -#undef ELF_ARCH #undef elf_check_arch #define elf_check_arch compat_elf_check_arch @@ -90,11 +90,6 @@ #define ELF_ET_DYN_BASE COMPAT_ELF_ET_DYN_BASE #endif -#ifdef COMPAT_ELF_EXEC_PAGESIZE -#undef ELF_EXEC_PAGESIZE -#define ELF_EXEC_PAGESIZE COMPAT_ELF_EXEC_PAGESIZE -#endif - #ifdef COMPAT_ELF_PLAT_INIT #undef ELF_PLAT_INIT #define ELF_PLAT_INIT COMPAT_ELF_PLAT_INIT diff --git a/include/linux/elfcore-compat.h b/include/linux/elfcore-compat.h index 10485f0c9740..e272c3d452ce 100644 --- a/include/linux/elfcore-compat.h +++ b/include/linux/elfcore-compat.h @@ -17,7 +17,7 @@ struct compat_elf_siginfo compat_int_t si_errno; }; -struct compat_elf_prstatus +struct compat_elf_prstatus_common { struct compat_elf_siginfo pr_info; short pr_cursig; @@ -31,8 +31,6 @@ struct compat_elf_prstatus struct old_timeval32 pr_stime; struct old_timeval32 pr_cutime; struct old_timeval32 pr_cstime; - compat_elf_gregset_t pr_reg; - compat_int_t pr_fpvalid; }; struct compat_elf_prpsinfo @@ -49,4 +47,15 @@ struct compat_elf_prpsinfo char pr_psargs[ELF_PRARGSZ]; }; +#ifdef CONFIG_ARCH_HAS_ELFCORE_COMPAT +#include <asm/elfcore-compat.h> +#endif + +struct compat_elf_prstatus +{ + struct compat_elf_prstatus_common common; + compat_elf_gregset_t pr_reg; + compat_int_t pr_fpvalid; +}; + #endif /* _LINUX_ELFCORE_COMPAT_H */ diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index de51c1bef27d..2aaa15779d50 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -29,7 +29,7 @@ struct elf_siginfo * the SVR4 structure, but more Linuxy, with things that Linux does * not support and which gdb doesn't really use excluded. */ -struct elf_prstatus +struct elf_prstatus_common { struct elf_siginfo pr_info; /* Info associated with signal */ short pr_cursig; /* Current signal */ @@ -43,6 +43,11 @@ struct elf_prstatus struct __kernel_old_timeval pr_stime; /* System time */ struct __kernel_old_timeval pr_cutime; /* Cumulative user time */ struct __kernel_old_timeval pr_cstime; /* Cumulative system time */ +}; + +struct elf_prstatus +{ + struct elf_prstatus_common common; elf_gregset_t pr_reg; /* GP registers */ int pr_fpvalid; /* True if math co-processor being used. */ }; diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index aa919585c24b..a0b6780740c8 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1076,7 +1076,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu) if (!buf) return; memset(&prstatus, 0, sizeof(prstatus)); - prstatus.pr_pid = current->pid; + prstatus.common.pr_pid = current->pid; elf_core_copy_kernel_regs(&prstatus.pr_reg, regs); buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, &prstatus, sizeof(prstatus)); |