1
0
Fork 0

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
master
Linus Torvalds 2021-02-21 09:29:23 -08:00
commit 591fd30eee
27 changed files with 129 additions and 339 deletions

View File

@ -1111,6 +1111,9 @@ config ARCH_SPLIT_ARG64
If a 32-bit architecture requires 64-bit arguments to be split into If a 32-bit architecture requires 64-bit arguments to be split into
pairs of 32-bit arguments, select this option. pairs of 32-bit arguments, select this option.
config ARCH_HAS_ELFCORE_COMPAT
bool
source "kernel/gcov/Kconfig" source "kernel/gcov/Kconfig"
source "scripts/gcc-plugins/Kconfig" source "scripts/gcc-plugins/Kconfig"

View File

@ -1213,7 +1213,6 @@ config ARM64_TAGGED_ADDR_ABI
menuconfig COMPAT menuconfig COMPAT
bool "Kernel support for 32-bit EL0" bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT depends on ARM64_4K_PAGES || EXPERT
select COMPAT_BINFMT_ELF if BINFMT_ELF
select HAVE_UID16 select HAVE_UID16
select OLD_SIGSUSPEND3 select OLD_SIGSUSPEND3
select COMPAT_OLD_SIGACTION select COMPAT_OLD_SIGACTION

View File

@ -43,7 +43,7 @@ crash_save_this_cpu(void)
elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg); elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
memset(prstatus, 0, sizeof(*prstatus)); memset(prstatus, 0, sizeof(*prstatus));
prstatus->pr_pid = current->pid; prstatus->common.pr_pid = current->pid;
ia64_dump_cpu_regs(dst); ia64_dump_cpu_regs(dst);
cfm = dst[43]; cfm = dst[43];

View File

@ -92,6 +92,7 @@ config MIPS
select SET_FS select SET_FS
select SYSCTL_EXCEPTION_TRACE select SYSCTL_EXCEPTION_TRACE
select VIRT_TO_BUS select VIRT_TO_BUS
select ARCH_HAS_ELFCORE_COMPAT
config MIPS_FIXUP_BIGPHYS_ADDR config MIPS_FIXUP_BIGPHYS_ADDR
bool bool
@ -2182,7 +2183,7 @@ endchoice
config KVM_GUEST config KVM_GUEST
bool "KVM Guest Kernel" bool "KVM Guest Kernel"
depends on CPU_MIPS32_R2 depends on CPU_MIPS32_R2
depends on BROKEN_ON_SMP depends on !64BIT && BROKEN_ON_SMP
help help
Select this option if building a guest kernel for KVM (Trap & Emulate) Select this option if building a guest kernel for KVM (Trap & Emulate)
mode. mode.
@ -3300,11 +3301,6 @@ config MIPS32_N32
If unsure, say N. If unsure, say N.
config BINFMT_ELF32
bool
default y if MIPS32_O32 || MIPS32_N32
select ELFCORE
menu "Power management options" menu "Power management options"
config ARCH_HIBERNATION_POSSIBLE config ARCH_HIBERNATION_POSSIBLE

View File

@ -201,7 +201,6 @@ struct mips_elf_abiflags_v0 {
uint32_t flags2; uint32_t flags2;
}; };
#ifndef ELF_ARCH
/* ELF register definitions */ /* ELF register definitions */
#define ELF_NGREG 45 #define ELF_NGREG 45
#define ELF_NFPREG 33 #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. * 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. * 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. * 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. * 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 #endif
#define ELF_ARCH EM_MIPS #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 * 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 * 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 #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; \ int __res = 1; \
struct elfhdr *__h = (hdr); \ struct elfhdr *__h = (hdr); \
@ -288,21 +286,26 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
__res = 0; \ __res = 0; \
if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ if (__h->e_ident[EI_CLASS] != ELFCLASS32) \
__res = 0; \ __res = 0; \
if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ if ((__h->e_flags & EF_MIPS_ABI2) != 0) { \
__res = 0; \ if (!IS_ENABLED(CONFIG_MIPS32_N32) || \
if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ (__h->e_flags & EF_MIPS_ABI)) \
((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ __res = 0; \
__res = 0; \ } else { \
if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32)) \
__res = 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; \
} \
__res; \ __res; \
}) })
/* /*
* Return non-zero if HDR identifies an n64 ELF binary. * Return non-zero if HDR identifies an n64 ELF binary.
*/ */
#define elfn64_check_arch(hdr) \ #define elf64_check_arch(hdr) \
({ \ ({ \
int __res = 1; \ int __res = 1; \
struct elfhdr *__h = (hdr); \ struct elfhdr *__h = (hdr); \
@ -315,25 +318,6 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
__res; \ __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; struct mips_abi;
extern struct mips_abi 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 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. */ 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) #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif
/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \ #define ARCH_DLINFO \

View File

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

View File

@ -80,8 +80,8 @@ obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_32BIT) += scall32-o32.o
obj-$(CONFIG_64BIT) += scall64-n64.o obj-$(CONFIG_64BIT) += scall64-n64.o
obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.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_N32) += scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o signal_o32.o obj-$(CONFIG_MIPS32_O32) += scall64-o32.o signal_o32.o
obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o

View File

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

View File

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

View File

@ -20,7 +20,7 @@
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/war.h> #include <asm/war.h>
#ifndef CONFIG_BINFMT_ELF32 #ifndef CONFIG_MIPS32_COMPAT
/* Neither O32 nor N32, so define handle_sys here */ /* Neither O32 nor N32, so define handle_sys here */
#define handle_sys64 handle_sys #define handle_sys64 handle_sys
#endif #endif

View File

@ -335,7 +335,6 @@ source "kernel/Kconfig.hz"
config COMPAT config COMPAT
def_bool y def_bool y
depends on 64BIT depends on 64BIT
select COMPAT_BINFMT_ELF if BINFMT_ELF
config SYSVIPC_COMPAT config SYSVIPC_COMPAT
def_bool y def_bool y

View File

@ -282,7 +282,6 @@ config COMPAT
bool "Enable support for 32bit binaries" bool "Enable support for 32bit binaries"
depends on PPC64 depends on PPC64
default y if !CPU_LITTLE_ENDIAN default y if !CPU_LITTLE_ENDIAN
select COMPAT_BINFMT_ELF
select ARCH_WANT_OLD_COMPAT_IPC select ARCH_WANT_OLD_COMPAT_IPC
select COMPAT_OLD_SIGACTION select COMPAT_OLD_SIGACTION

View File

@ -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' * As a PIR value could also be '0', add an offset of '100'
* to every PIR to avoid misinterpretations in GDB. * to every PIR to avoid misinterpretations in GDB.
*/ */
prstatus->pr_pid = cpu_to_be32(100 + pir); prstatus->common.pr_pid = cpu_to_be32(100 + pir);
prstatus->pr_ppid = cpu_to_be32(1); prstatus->common.pr_ppid = cpu_to_be32(1);
/* /*
* Indicate SIGUSR1 for crash initiated from kernel. * Indicate SIGUSR1 for crash initiated from kernel.
@ -130,7 +130,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir,
short sig; short sig;
sig = kernel_initiated ? SIGUSR1 : SIGTERM; sig = kernel_initiated ? SIGUSR1 : SIGTERM;
prstatus->pr_cursig = cpu_to_be16(sig); prstatus->common.pr_cursig = cpu_to_be16(sig);
} }
} }

View File

@ -426,7 +426,6 @@ config 64BIT
config COMPAT config COMPAT
def_bool y def_bool y
prompt "Kernel support for 31 bit emulation" prompt "Kernel support for 31 bit emulation"
select COMPAT_BINFMT_ELF if BINFMT_ELF
select ARCH_WANT_OLD_COMPAT_IPC select ARCH_WANT_OLD_COMPAT_IPC
select COMPAT_OLD_SIGACTION select COMPAT_OLD_SIGACTION
select HAVE_UID16 select HAVE_UID16

View File

@ -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.gprs, sa->gprs, sizeof(sa->gprs));
memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw)); memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs)); 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 */ /* Prepare fpregset (floating point) note */
memset(&nt_fpregset, 0, sizeof(nt_fpregset)); memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc)); memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc));

View File

@ -494,7 +494,6 @@ config COMPAT
bool bool
depends on SPARC64 depends on SPARC64
default y default y
select COMPAT_BINFMT_ELF
select HAVE_UID16 select HAVE_UID16
select ARCH_WANT_OLD_COMPAT_IPC select ARCH_WANT_OLD_COMPAT_IPC
select COMPAT_OLD_SIGACTION select COMPAT_OLD_SIGACTION

View File

@ -32,6 +32,7 @@ config X86_64
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE select NEED_DMA_MAP_STATE
select SWIOTLB select SWIOTLB
select ARCH_HAS_ELFCORE_COMPAT
config FORCE_DYNAMIC_FTRACE config FORCE_DYNAMIC_FTRACE
def_bool y def_bool y
@ -2860,7 +2861,6 @@ config IA32_EMULATION
depends on X86_64 depends on X86_64
select ARCH_WANT_OLD_COMPAT_IPC select ARCH_WANT_OLD_COMPAT_IPC
select BINFMT_ELF select BINFMT_ELF
select COMPAT_BINFMT_ELF
select COMPAT_OLD_SIGACTION select COMPAT_OLD_SIGACTION
help help
Include code to run legacy 32-bit programs under a Include code to run legacy 32-bit programs under a

View File

@ -159,17 +159,6 @@ struct compat_shmid64_ds {
compat_ulong_t __unused5; 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 #ifdef CONFIG_X86_X32_ABI
#define COMPAT_USE_64BIT_TIME \ #define COMPAT_USE_64BIT_TIME \
(!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)) (!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT))

View File

@ -364,7 +364,7 @@ do { \
#define COMPAT_ARCH_DLINFO \ #define COMPAT_ARCH_DLINFO \
if (exec->e_machine == EM_X86_64) \ if (exec->e_machine == EM_X86_64) \
ARCH_DLINFO_X32; \ ARCH_DLINFO_X32; \
else \ else if (IS_ENABLED(CONFIG_IA32_EMULATION)) \
ARCH_DLINFO_IA32 ARCH_DLINFO_IA32
#define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) #define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)

View File

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

View File

@ -29,7 +29,7 @@ config BINFMT_ELF
latest version). latest version).
config COMPAT_BINFMT_ELF config COMPAT_BINFMT_ELF
bool def_bool y
depends on COMPAT && BINFMT_ELF depends on COMPAT && BINFMT_ELF
select ELFCORE select ELFCORE

View File

@ -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 * fill up all the fields in prstatus from the given task struct, except
* registers which need to be filled up separately. * 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) struct task_struct *p, long signr)
{ {
prstatus->pr_info.si_signo = prstatus->pr_cursig = 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 #ifndef PRSTATUS_SIZE
#define PRSTATUS_SIZE(S, R) sizeof(S) #define PRSTATUS_SIZE sizeof(struct elf_prstatus)
#endif #endif
#ifndef SET_PR_FPVALID #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 #endif
static int fill_thread_core_info(struct elf_thread_core_info *t, 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) long signr, size_t *total)
{ {
unsigned int i; unsigned int i;
int regset0_size;
/* /*
* NT_PRSTATUS is the one special case, because the regset data * 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. * than being the whole note contents. We fill the reset in here.
* We assume that regset 0 is NT_PRSTATUS. * We assume that regset 0 is NT_PRSTATUS.
*/ */
fill_prstatus(&t->prstatus, t->task, signr); fill_prstatus(&t->prstatus.common, t->task, signr);
regset0_size = regset_get(t->task, &view->regsets[0], regset_get(t->task, &view->regsets[0],
sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);
if (regset0_size < 0)
return 0;
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, 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]); *total += notesize(&t->notes[0]);
do_thread_regset_writeback(t->task, &view->regsets[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; continue;
if (is_fpreg) 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", fill_note(&t->notes[i], is_fpreg ? "CORE" : "LINUX",
note_type, ret, data); 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; struct task_struct *p = t->thread;
t->num_notes = 0; 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); elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), 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 */ /* now collect the dump for the current */
memset(info->prstatus, 0, sizeof(*info->prstatus)); 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); elf_core_copy_regs(&info->prstatus->pr_reg, regs);
/* Set up header */ /* Set up header */

View File

@ -1191,18 +1191,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
struct elf_prstatus_fdpic struct elf_prstatus_fdpic
{ {
struct elf_siginfo pr_info; /* Info associated with signal */ struct elf_prstatus_common common;
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 */
elf_gregset_t pr_reg; /* GP registers */ elf_gregset_t pr_reg; /* GP registers */
/* When using FDPIC, the loadmap addresses need to be communicated /* When using FDPIC, the loadmap addresses need to be communicated
* to GDB in order for GDB to do the necessary relocations. The * 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 * fill up all the fields in prstatus from the given task struct, except
* registers which need to be filled up separately. * 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) struct task_struct *p, long signr)
{ {
prstatus->pr_info.si_signo = prstatus->pr_cursig = 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_cutime = ns_to_kernel_old_timeval(p->signal->cutime);
prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime); 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, 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) if (!t)
return 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], regset_get(p, &view->regsets[0],
sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);

View File

@ -50,6 +50,7 @@
* which requires asm/elf.h to define compat_elf_gregset_t et al. * which requires asm/elf.h to define compat_elf_gregset_t et al.
*/ */
#define elf_prstatus compat_elf_prstatus #define elf_prstatus compat_elf_prstatus
#define elf_prstatus_common compat_elf_prstatus_common
#define elf_prpsinfo compat_elf_prpsinfo #define elf_prpsinfo compat_elf_prpsinfo
#undef ns_to_kernel_old_timeval #undef ns_to_kernel_old_timeval
@ -61,7 +62,6 @@
* differ from the native ones, or omitted when they match. * differ from the native ones, or omitted when they match.
*/ */
#undef ELF_ARCH
#undef elf_check_arch #undef elf_check_arch
#define elf_check_arch compat_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 #define ELF_ET_DYN_BASE COMPAT_ELF_ET_DYN_BASE
#endif #endif
#ifdef COMPAT_ELF_EXEC_PAGESIZE
#undef ELF_EXEC_PAGESIZE
#define ELF_EXEC_PAGESIZE COMPAT_ELF_EXEC_PAGESIZE
#endif
#ifdef COMPAT_ELF_PLAT_INIT #ifdef COMPAT_ELF_PLAT_INIT
#undef ELF_PLAT_INIT #undef ELF_PLAT_INIT
#define ELF_PLAT_INIT COMPAT_ELF_PLAT_INIT #define ELF_PLAT_INIT COMPAT_ELF_PLAT_INIT

View File

@ -17,7 +17,7 @@ struct compat_elf_siginfo
compat_int_t si_errno; compat_int_t si_errno;
}; };
struct compat_elf_prstatus struct compat_elf_prstatus_common
{ {
struct compat_elf_siginfo pr_info; struct compat_elf_siginfo pr_info;
short pr_cursig; short pr_cursig;
@ -31,8 +31,6 @@ struct compat_elf_prstatus
struct old_timeval32 pr_stime; struct old_timeval32 pr_stime;
struct old_timeval32 pr_cutime; struct old_timeval32 pr_cutime;
struct old_timeval32 pr_cstime; struct old_timeval32 pr_cstime;
compat_elf_gregset_t pr_reg;
compat_int_t pr_fpvalid;
}; };
struct compat_elf_prpsinfo struct compat_elf_prpsinfo
@ -49,4 +47,15 @@ struct compat_elf_prpsinfo
char pr_psargs[ELF_PRARGSZ]; 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 */ #endif /* _LINUX_ELFCORE_COMPAT_H */

View File

@ -29,7 +29,7 @@ struct elf_siginfo
* the SVR4 structure, but more Linuxy, with things that Linux does * the SVR4 structure, but more Linuxy, with things that Linux does
* not support and which gdb doesn't really use excluded. * 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 */ struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current 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_stime; /* System time */
struct __kernel_old_timeval pr_cutime; /* Cumulative user time */ struct __kernel_old_timeval pr_cutime; /* Cumulative user time */
struct __kernel_old_timeval pr_cstime; /* Cumulative system 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 */ elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */ int pr_fpvalid; /* True if math co-processor being used. */
}; };

View File

@ -1076,7 +1076,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
if (!buf) if (!buf)
return; return;
memset(&prstatus, 0, sizeof(prstatus)); 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); elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
&prstatus, sizeof(prstatus)); &prstatus, sizeof(prstatus));