diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 20:29:23 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 20:29:23 +0300 |
commit | 591fd30eee47ed75d1296d619dd467414d0894e3 (patch) | |
tree | f3fd8b651b9143194c6a1480ba3f7ecaea84feae /arch/mips | |
parent | 054560e961a0ee4067fccfcfa943335e1aa48928 (diff) | |
parent | e565d89e4aa07e3f20ac5e8757b1da24b5878e69 (diff) | |
download | linux-591fd30eee47ed75d1296d619dd467414d0894e3.tar.xz |
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
Diffstat (limited to 'arch/mips')
-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 |
7 files changed, 53 insertions, 275 deletions
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 |