[PATCH 2/7] kexec: bypass check on interp program header for ppc64le zImage

Cédric Le Goater clg at fr.ibm.com
Fri Apr 18 07:08:35 PDT 2014


When the elf information is built from the executable, kexec checks
for an interp elf program header and fails if it exists. The following
patch adds a new service machine_check_elf_phdr_interp() which lets
platforms eventually bypass this check.

This is needed for the zImage boot wrapper on PPC 64bit little endian.
The executable is linked as position independent and has a interp elf
program header.

An alternative to this patch would be to remove the whole test on the
interp elf program header as kexec seems to be ignoring the information
after all.

Signed-off-by: Cédric Le Goater <clg at fr.ibm.com>
---
 kexec/arch/arm/kexec-elf-rel-arm.c       |    5 +++++
 kexec/arch/cris/kexec-elf-rel-cris.c     |    5 +++++
 kexec/arch/i386/kexec-elf-rel-x86.c      |    5 +++++
 kexec/arch/ia64/kexec-elf-rel-ia64.c     |    5 +++++
 kexec/arch/m68k/kexec-elf-rel-m68k.c     |    5 +++++
 kexec/arch/mips/kexec-elf-rel-mips.c     |    5 +++++
 kexec/arch/ppc/kexec-elf-rel-ppc.c       |    5 +++++
 kexec/arch/ppc64/kexec-elf-rel-ppc64.c   |   16 ++++++++++++++++
 kexec/arch/s390/kexec-elf-rel-s390.c     |    5 +++++
 kexec/arch/sh/kexec-elf-rel-sh.c         |    5 +++++
 kexec/arch/x86_64/kexec-elf-rel-x86_64.c |    5 +++++
 kexec/kexec-elf-exec.c                   |    4 ++++
 kexec/kexec-elf.h                        |    1 +
 13 files changed, 71 insertions(+)

diff --git a/kexec/arch/arm/kexec-elf-rel-arm.c b/kexec/arch/arm/kexec-elf-rel-arm.c
index 214f0ccc2a33..6fbe8c485447 100644
--- a/kexec/arch/arm/kexec-elf-rel-arm.c
+++ b/kexec/arch/arm/kexec-elf-rel-arm.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/cris/kexec-elf-rel-cris.c b/kexec/arch/cris/kexec-elf-rel-cris.c
index c4427cc144be..b0add16444ad 100644
--- a/kexec/arch/cris/kexec-elf-rel-cris.c
+++ b/kexec/arch/cris/kexec-elf-rel-cris.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/i386/kexec-elf-rel-x86.c b/kexec/arch/i386/kexec-elf-rel-x86.c
index fdc3d52feeb2..c7d783e70ecc 100644
--- a/kexec/arch/i386/kexec-elf-rel-x86.c
+++ b/kexec/arch/i386/kexec-elf-rel-x86.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/arch/ia64/kexec-elf-rel-ia64.c b/kexec/arch/ia64/kexec-elf-rel-ia64.c
index cfb106169643..a2aec0d03e3f 100644
--- a/kexec/arch/ia64/kexec-elf-rel-ia64.c
+++ b/kexec/arch/ia64/kexec-elf-rel-ia64.c
@@ -32,6 +32,11 @@
 
 #define MAX_LTOFF       ((uint64_t) (1 << 22))
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/arch/m68k/kexec-elf-rel-m68k.c b/kexec/arch/m68k/kexec-elf-rel-m68k.c
index fa12a1670149..bc9fd1aa9899 100644
--- a/kexec/arch/m68k/kexec-elf-rel-m68k.c
+++ b/kexec/arch/m68k/kexec-elf-rel-m68k.c
@@ -12,6 +12,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB)
diff --git a/kexec/arch/mips/kexec-elf-rel-mips.c b/kexec/arch/mips/kexec-elf-rel-mips.c
index 6f436393a87a..8789e3366aa1 100644
--- a/kexec/arch/mips/kexec-elf-rel-mips.c
+++ b/kexec/arch/mips/kexec-elf-rel-mips.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/ppc/kexec-elf-rel-ppc.c b/kexec/arch/ppc/kexec-elf-rel-ppc.c
index 90a66f420409..a8ab54e0c0c6 100644
--- a/kexec/arch/ppc/kexec-elf-rel-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-rel-ppc.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
index 708f507a50a6..300f15149542 100644
--- a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
@@ -5,6 +5,22 @@
 #include "../../kexec-elf.h"
 #include "kexec-ppc64.h"
 
+/* The zImage boot wrapper on 64bit little endian is linked as a
+ * position independant executable and has a interp program
+ * header. We don't want to check for it.
+ */
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	if (ehdr->ei_data == ELFDATA2MSB)
+		return 1;
+
+	/* sections are loaded in build_elf_info */
+	if (elf_rel_find_section(ehdr, ".kernel:vmlinux.strip"))
+		return 0;
+
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_class != ELFCLASS64) {
diff --git a/kexec/arch/s390/kexec-elf-rel-s390.c b/kexec/arch/s390/kexec-elf-rel-s390.c
index 80bcd1bb92ef..df2d15af88cd 100644
--- a/kexec/arch/s390/kexec-elf-rel-s390.c
+++ b/kexec/arch/s390/kexec-elf-rel-s390.c
@@ -12,6 +12,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB)
diff --git a/kexec/arch/sh/kexec-elf-rel-sh.c b/kexec/arch/sh/kexec-elf-rel-sh.c
index 0bfc45ec0d6d..5db74ea91213 100644
--- a/kexec/arch/sh/kexec-elf-rel-sh.c
+++ b/kexec/arch/sh/kexec-elf-rel-sh.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	/* Intentionally don't bother with endianness validation, it's
diff --git a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
index c795037cdb0f..6ddc28198882 100644
--- a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
+++ b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/kexec-elf-exec.c b/kexec/kexec-elf-exec.c
index cb62d04849e5..adc794d32481 100644
--- a/kexec/kexec-elf-exec.c
+++ b/kexec/kexec-elf-exec.c
@@ -33,6 +33,10 @@ int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
 		fprintf(stderr, "No ELF program header\n");
 		return -1; 
 	}
+
+	if (!machine_check_elf_phdr_interp(ehdr))
+		return 0;
+
 	end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
 	for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
 		/* Kexec does not support loading interpreters.
diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h
index 19b5769d1838..739639418429 100644
--- a/kexec/kexec-elf.h
+++ b/kexec/kexec-elf.h
@@ -133,5 +133,6 @@ unsigned long elf_max_addr(const struct mem_ehdr *ehdr);
 extern int machine_verify_elf_rel(struct mem_ehdr *ehdr);
 extern void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, 
 	void *location, unsigned long address, unsigned long value);
+extern int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr);
 #endif /* KEXEC_ELF_H */
 
-- 
1.7.10.4




More information about the kexec mailing list