linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/11] kexec_file: Clean up purgatory load
@ 2018-03-21 11:27 Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 01/11] kexec_file: Silence compile warnings Philipp Rudo
                   ` (12 more replies)
  0 siblings, 13 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

Hi everybody

here is the updated patch set including Dave's comments.

Changes v1 -> v2:
	* Fix missing memcpy and memset definition in x86 purgatory
	introduced by moving the sha256 implementation to common code.
	* Update subject of patches #7-9 to be more precise.
	* Add missing semicolon in patch #7 found by kbuild bot.
	* Fix compile warnings found by kbuild bot by moving all kexec_file
	specific function declarations into a 'ifdef CONFIG_KEXEC_FILE'
	block (patch #5 and #10).

Thanks
Philipp

---

Hi everybody

following the discussion with Dave and AKASHI, here are the common code
patches extracted from my recent patch set (Add kexec_file_load support to
s390) [1]. The patches were extracted to allow upstream integration together
with AKASHI's common code patches before the arch code gets adjusted to the
new base.

The reason for this series is to prepare common code for adding
kexec_file_load to s390 as well as cleaning up the mis-use of the sh_offset
field during purgatory load. In detail this series contains:

Patch #1&2: Minor cleanups/fixes.

Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
depending on the section. With these patches the section address will be
calculated verbosely and sh_offset will contain the offset of the section
in the stripped purgatory binary (purgatory_buf).

Patch #10: Allows architectures to set the purgatory load address. This
patch is important for s390 as the kernel and purgatory have to be loaded
to fixed addresses. In current code this is impossible as the purgatory
load is opaque to the architecture.

Patch #11: Moves x86 purgatories sha implementation to common lib/
directory to allow reuse in other architectures.

The patches apply to v4.16-rc3. There are no changes compared to [1] (all
requested changes only affected s390 code). Please note that I had to touch
arch code for x86 and power a little. In theory this should not change the
behavior but I don't have a way to test it. Cross-compiling with
defconfig [2] works fine for both.

Thanks
Philipp

[1] http://lists.infradead.org/pipermail/kexec/2018-February/019926.html
[2] On x86 with the orc unwinder and stack validation turned off. objtool
    SEGFAULTs on s390...

Philipp Rudo (11):
  kexec_file: Silence compile warnings
  kexec_file: Remove checks in kexec_purgatory_load
  kexec_file: Make purgatory_info->ehdr const
  kexec_file: Search symbols in read-only kexec_purgatory
  kexec_file: Use read-only sections in arch_kexec_apply_relocations*
  kexec_file: Split up __kexec_load_puragory
  kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs
  kexec_file: Remove unneeded variables in kexec_purgatory_setup_sechdrs
  kexec_file: Remove mis-use of sh_offset field during purgatory load
  kexec_file: Allow archs to set purgatory load address
  kexec_file: Move purgatories sha256 to common code

 arch/powerpc/kernel/kexec_elf_64.c             |   9 +-
 arch/x86/kernel/kexec-bzimage64.c              |   8 +-
 arch/x86/kernel/machine_kexec_64.c             |  66 ++---
 arch/x86/purgatory/Makefile                    |   3 +
 arch/x86/purgatory/purgatory.c                 |   2 +-
 arch/x86/purgatory/string.c                    |  12 +
 include/linux/kexec.h                          |  49 ++--
 {arch/x86/purgatory => include/linux}/sha256.h |  11 +-
 kernel/kexec_file.c                            | 379 ++++++++++++-------------
 {arch/x86/purgatory => lib}/sha256.c           |   4 +-
 10 files changed, 267 insertions(+), 276 deletions(-)
 rename {arch/x86/purgatory => include/linux}/sha256.h (62%)
 rename {arch/x86/purgatory => lib}/sha256.c (99%)

-- 
2.13.5

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 01/11] kexec_file: Silence compile warnings
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 02/11] kexec_file: Remove checks in kexec_purgatory_load Philipp Rudo
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

When building the kernel with CONFIG_KEXEC_FILE enabled gcc prints a
compile warning multiple times.

In file included from <path>/linux/init/initramfs.c:526:0:
<path>/include/linux/kexec.h:120:9: warning: ‘struct kimage’ declared inside parameter list [enabled by default]
         unsigned long cmdline_len);
         ^
This is because the typedefs for kexec_file_load uses struct kimage before
it is declared. Fix this by simply forward declaring struct kimage.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 include/linux/kexec.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f16f6ceb3875..7bae5e87bf0d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -114,6 +114,8 @@ struct purgatory_info {
 	unsigned long purgatory_load_addr;
 };
 
+struct kimage;
+
 typedef int (kexec_probe_t)(const char *kernel_buf, unsigned long kernel_size);
 typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
 			     unsigned long kernel_len, char *initrd,
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 02/11] kexec_file: Remove checks in kexec_purgatory_load
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 01/11] kexec_file: Silence compile warnings Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 03/11] kexec_file: Make purgatory_info->ehdr const Philipp Rudo
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

Before the purgatory is loaded several checks are done whether the ELF file
in kexec_purgatory is valid or not. These checks are incomplete. For
example they don't check for the total size of the sections defined in the
section header table or if the entry point actually points into the
purgatory.

On the other hand the purgatory, although an ELF file on its own, is part
of the kernel. Thus not trusting the purgatory means not trusting the
kernel build itself.

So remove all validity checks on the purgatory and just trust the kernel
build.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 kernel/kexec_file.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index e5bcd94c1efb..0f044457b40c 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -880,22 +880,8 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 	if (kexec_purgatory_size <= 0)
 		return -EINVAL;
 
-	if (kexec_purgatory_size < sizeof(Elf_Ehdr))
-		return -ENOEXEC;
-
 	pi->ehdr = (Elf_Ehdr *)kexec_purgatory;
 
-	if (memcmp(pi->ehdr->e_ident, ELFMAG, SELFMAG) != 0
-	    || pi->ehdr->e_type != ET_REL
-	    || !elf_check_arch(pi->ehdr)
-	    || pi->ehdr->e_shentsize != sizeof(Elf_Shdr))
-		return -ENOEXEC;
-
-	if (pi->ehdr->e_shoff >= kexec_purgatory_size
-	    || (pi->ehdr->e_shnum * sizeof(Elf_Shdr) >
-	    kexec_purgatory_size - pi->ehdr->e_shoff))
-		return -ENOEXEC;
-
 	ret = __kexec_load_purgatory(image, min, max, top_down);
 	if (ret)
 		return ret;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 03/11] kexec_file: Make purgatory_info->ehdr const
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 01/11] kexec_file: Silence compile warnings Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 02/11] kexec_file: Remove checks in kexec_purgatory_load Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 04/11] kexec_file: Search symbols in read-only kexec_purgatory Philipp Rudo
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

The kexec_purgatory buffer is read-only. Thus all pointers into
kexec_purgatory are read-only, too. Point this out by explicitly marking
purgatory_info->ehdr as 'const' and update the comments in purgatory_info.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 include/linux/kexec.h | 17 +++++++++++------
 kernel/kexec_file.c   |  4 ++--
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 7bae5e87bf0d..10842eece180 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -99,14 +99,19 @@ struct compat_kexec_segment {
 
 #ifdef CONFIG_KEXEC_FILE
 struct purgatory_info {
-	/* Pointer to elf header of read only purgatory */
-	Elf_Ehdr *ehdr;
-
-	/* Pointer to purgatory sechdrs which are modifiable */
+	/*
+	 * Pointer to elf header at the beginning of kexec_purgatory.
+	 * Note: kexec_purgatory is read only
+	 */
+	const Elf_Ehdr *ehdr;
+	/*
+	 * Temporary, modifiable buffer for sechdrs used for relocation.
+	 * This memory can be freed post image load.
+	 */
 	Elf_Shdr *sechdrs;
 	/*
-	 * Temporary buffer location where purgatory is loaded and relocated
-	 * This memory can be freed post image load
+	 * Temporary, modifiable buffer for stripped purgatory used for
+	 * relocation. This memory can be freed post image load.
 	 */
 	void *purgatory_buf;
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 0f044457b40c..06fc9fdd2474 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -880,7 +880,7 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 	if (kexec_purgatory_size <= 0)
 		return -EINVAL;
 
-	pi->ehdr = (Elf_Ehdr *)kexec_purgatory;
+	pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
 
 	ret = __kexec_load_purgatory(image, min, max, top_down);
 	if (ret)
@@ -904,9 +904,9 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
 					    const char *name)
 {
+	const Elf_Ehdr *ehdr;
 	Elf_Sym *syms;
 	Elf_Shdr *sechdrs;
-	Elf_Ehdr *ehdr;
 	int i, k;
 	const char *strtab;
 
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 04/11] kexec_file: Search symbols in read-only kexec_purgatory
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (2 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 03/11] kexec_file: Make purgatory_info->ehdr const Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations* Philipp Rudo
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

The stripped purgatory does not contain a symtab. So when looking for
symbols this is done in read-only kexec_purgatory. Highlight this by
marking the corresponding variables as 'const'.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 kernel/kexec_file.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 06fc9fdd2474..2072b288ec53 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -901,20 +901,27 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 	return ret;
 }
 
-static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
-					    const char *name)
+/*
+ * kexec_purgatory_find_symbol - find a symbol in the purgatory
+ * @pi:		Purgatory to search in.
+ * @name:	Name of the symbol.
+ *
+ * Return: pointer to symbol in read-only symtab on success, NULL on error.
+ */
+static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
+						  const char *name)
 {
+	const Elf_Shdr *sechdrs;
 	const Elf_Ehdr *ehdr;
-	Elf_Sym *syms;
-	Elf_Shdr *sechdrs;
-	int i, k;
+	const Elf_Sym *syms;
 	const char *strtab;
+	int i, k;
 
-	if (!pi->sechdrs || !pi->ehdr)
+	if (!pi->ehdr)
 		return NULL;
 
-	sechdrs = pi->sechdrs;
 	ehdr = pi->ehdr;
+	sechdrs = (void *)ehdr + ehdr->e_shoff;
 
 	for (i = 0; i < ehdr->e_shnum; i++) {
 		if (sechdrs[i].sh_type != SHT_SYMTAB)
@@ -923,8 +930,8 @@ static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
 		if (sechdrs[i].sh_link >= ehdr->e_shnum)
 			/* Invalid strtab section number */
 			continue;
-		strtab = (char *)sechdrs[sechdrs[i].sh_link].sh_offset;
-		syms = (Elf_Sym *)sechdrs[i].sh_offset;
+		strtab = (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset;
+		syms = (void *)ehdr + sechdrs[i].sh_offset;
 
 		/* Go through symbols for a match */
 		for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) {
@@ -952,7 +959,7 @@ static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
 void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
 {
 	struct purgatory_info *pi = &image->purgatory_info;
-	Elf_Sym *sym;
+	const Elf_Sym *sym;
 	Elf_Shdr *sechdr;
 
 	sym = kexec_purgatory_find_symbol(pi, name);
@@ -975,9 +982,9 @@ void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
 int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
 				   void *buf, unsigned int size, bool get_value)
 {
-	Elf_Sym *sym;
-	Elf_Shdr *sechdrs;
 	struct purgatory_info *pi = &image->purgatory_info;
+	const Elf_Sym *sym;
+	Elf_Shdr *sec;
 	char *sym_buf;
 
 	sym = kexec_purgatory_find_symbol(pi, name);
@@ -990,16 +997,15 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
 		return -EINVAL;
 	}
 
-	sechdrs = pi->sechdrs;
+	sec = pi->sechdrs + sym->st_shndx;
 
-	if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
+	if (sec->sh_type == SHT_NOBITS) {
 		pr_err("symbol %s is in a bss section. Cannot %s\n", name,
 		       get_value ? "get" : "set");
 		return -EINVAL;
 	}
 
-	sym_buf = (unsigned char *)sechdrs[sym->st_shndx].sh_offset +
-					sym->st_value;
+	sym_buf = (char *)sec->sh_offset + sym->st_value;
 
 	if (get_value)
 		memcpy((void *)buf, sym_buf, size);
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations*
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (3 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 04/11] kexec_file: Search symbols in read-only kexec_purgatory Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 06/11] kexec_file: Split up __kexec_load_puragory Philipp Rudo
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

When the relocations are applied to the purgatory only the section the
relocations are applied to is writable. The other sections, i.e. the symtab
and .rel/.rela, are in read-only kexec_purgatory. Highlight this by marking
the corresponding variables as 'const'.

While at it also change the signatures of arch_kexec_apply_relocations* to
take section pointers instead of just the index of the relocation section.
This removes the second lookup and sanity check of the sections in arch
code.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 arch/x86/kernel/machine_kexec_64.c | 56 ++++++++++++---------------------
 include/linux/kexec.h              | 13 +++++---
 kernel/kexec_file.c                | 63 +++++++++++++++++++++++++-------------
 3 files changed, 71 insertions(+), 61 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 3b7427aa7d85..51667c8b5c9b 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -422,52 +422,36 @@ int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel,
 /*
  * Apply purgatory relocations.
  *
- * ehdr: Pointer to elf headers
- * sechdrs: Pointer to section headers.
- * relsec: section index of SHT_RELA section.
+ * @pi:		Purgatory to be relocated.
+ * @section:	Section relocations applying to.
+ * @relsec:	Section containing RELAs.
+ * @symtabsec:	Corresponding symtab.
  *
  * TODO: Some of the code belongs to generic code. Move that in kexec.c.
  */
-int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
-				     Elf64_Shdr *sechdrs, unsigned int relsec)
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+				     Elf_Shdr *section, const Elf_Shdr *relsec,
+				     const Elf_Shdr *symtabsec)
 {
 	unsigned int i;
 	Elf64_Rela *rel;
 	Elf64_Sym *sym;
 	void *location;
-	Elf64_Shdr *section, *symtabsec;
 	unsigned long address, sec_base, value;
 	const char *strtab, *name, *shstrtab;
+	const Elf_Shdr *sechdrs;
 
-	/*
-	 * ->sh_offset has been modified to keep the pointer to section
-	 * contents in memory
-	 */
-	rel = (void *)sechdrs[relsec].sh_offset;
-
-	/* Section to which relocations apply */
-	section = &sechdrs[sechdrs[relsec].sh_info];
-
-	pr_debug("Applying relocate section %u to %u\n", relsec,
-		 sechdrs[relsec].sh_info);
-
-	/* Associated symbol table */
-	symtabsec = &sechdrs[sechdrs[relsec].sh_link];
-
-	/* String table */
-	if (symtabsec->sh_link >= ehdr->e_shnum) {
-		/* Invalid strtab section number */
-		pr_err("Invalid string table section index %d\n",
-		       symtabsec->sh_link);
-		return -ENOEXEC;
-	}
+	/* String & section header string table */
+	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
+	strtab = (char *)pi->ehdr + sechdrs[symtabsec->sh_link].sh_offset;
+	shstrtab = (char *)pi->ehdr + sechdrs[pi->ehdr->e_shstrndx].sh_offset;
 
-	strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset;
+	rel = (void *)pi->ehdr + relsec->sh_offset;
 
-	/* section header string table */
-	shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset;
+	pr_debug("Applying relocate section %s to %u\n",
+		 shstrtab + relsec->sh_name, relsec->sh_info);
 
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+	for (i = 0; i < relsec->sh_size / sizeof(*rel); i++) {
 
 		/*
 		 * rel[i].r_offset contains byte offset from beginning
@@ -490,8 +474,8 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
 		 * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
 		 * these respectively.
 		 */
-		sym = (Elf64_Sym *)symtabsec->sh_offset +
-				ELF64_R_SYM(rel[i].r_info);
+		sym = (void *)pi->ehdr + symtabsec->sh_offset;
+		sym += ELF64_R_SYM(rel[i].r_info);
 
 		if (sym->st_name)
 			name = strtab + sym->st_name;
@@ -514,12 +498,12 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
 
 		if (sym->st_shndx == SHN_ABS)
 			sec_base = 0;
-		else if (sym->st_shndx >= ehdr->e_shnum) {
+		else if (sym->st_shndx >= pi->ehdr->e_shnum) {
 			pr_err("Invalid section %d for symbol %s\n",
 			       sym->st_shndx, name);
 			return -ENOEXEC;
 		} else
-			sec_base = sechdrs[sym->st_shndx].sh_addr;
+			sec_base = pi->sechdrs[sym->st_shndx].sh_addr;
 
 		value = sym->st_value;
 		value += sec_base;
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 10842eece180..a757ec37775f 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -166,6 +166,15 @@ struct kexec_buf {
 	bool top_down;
 };
 
+int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+					    Elf_Shdr *section,
+					    const Elf_Shdr *relsec,
+					    const Elf_Shdr *symtab);
+int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
+					Elf_Shdr *section,
+					const Elf_Shdr *relsec,
+					const Elf_Shdr *symtab);
+
 int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 			       int (*func)(struct resource *, void *));
 extern int kexec_add_buffer(struct kexec_buf *kbuf);
@@ -290,10 +299,6 @@ void * __weak arch_kexec_kernel_image_load(struct kimage *image);
 int __weak arch_kimage_file_post_load_cleanup(struct kimage *image);
 int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
 					unsigned long buf_len);
-int __weak arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr,
-					Elf_Shdr *sechdrs, unsigned int relsec);
-int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
-					unsigned int relsec);
 void arch_kexec_protect_crashkres(void);
 void arch_kexec_unprotect_crashkres(void);
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 2072b288ec53..80c7f658afc0 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -53,19 +53,35 @@ int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
 }
 #endif
 
-/* Apply relocations of type RELA */
+/*
+ * arch_kexec_apply_relocations_add - apply relocations of type RELA
+ * @pi:		Purgatory to be relocated.
+ * @section:	Section relocations applying to.
+ * @relsec:	Section containing RELAs.
+ * @symtab:	Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
 int __weak
-arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
-				 unsigned int relsec)
+arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
+				 const Elf_Shdr *relsec, const Elf_Shdr *symtab)
 {
 	pr_err("RELA relocation unsupported.\n");
 	return -ENOEXEC;
 }
 
-/* Apply relocations of type REL */
+/*
+ * arch_kexec_apply_relocations - apply relocations of type REL
+ * @pi:		Purgatory to be relocated.
+ * @section:	Section relocations applying to.
+ * @relsec:	Section containing RELs.
+ * @symtab:	Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
 int __weak
-arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
-			     unsigned int relsec)
+arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
+			     const Elf_Shdr *relsec, const Elf_Shdr *symtab)
 {
 	pr_err("REL relocation unsupported.\n");
 	return -ENOEXEC;
@@ -818,14 +834,19 @@ static int kexec_apply_relocations(struct kimage *image)
 {
 	int i, ret;
 	struct purgatory_info *pi = &image->purgatory_info;
-	Elf_Shdr *sechdrs = pi->sechdrs;
+	const Elf_Shdr *sechdrs;
+
+	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
 
-	/* Apply relocations */
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
-		Elf_Shdr *section, *symtab;
+		const Elf_Shdr *relsec;
+		const Elf_Shdr *symtab;
+		Elf_Shdr *section;
+
+		relsec = sechdrs + i;
 
-		if (sechdrs[i].sh_type != SHT_RELA &&
-		    sechdrs[i].sh_type != SHT_REL)
+		if (relsec->sh_type != SHT_RELA &&
+		    relsec->sh_type != SHT_REL)
 			continue;
 
 		/*
@@ -834,12 +855,12 @@ static int kexec_apply_relocations(struct kimage *image)
 		 * symbol table. And ->sh_info contains section header
 		 * index of section to which relocations apply.
 		 */
-		if (sechdrs[i].sh_info >= pi->ehdr->e_shnum ||
-		    sechdrs[i].sh_link >= pi->ehdr->e_shnum)
+		if (relsec->sh_info >= pi->ehdr->e_shnum ||
+		    relsec->sh_link >= pi->ehdr->e_shnum)
 			return -ENOEXEC;
 
-		section = &sechdrs[sechdrs[i].sh_info];
-		symtab = &sechdrs[sechdrs[i].sh_link];
+		section = pi->sechdrs + relsec->sh_info;
+		symtab = sechdrs + relsec->sh_link;
 
 		if (!(section->sh_flags & SHF_ALLOC))
 			continue;
@@ -856,12 +877,12 @@ static int kexec_apply_relocations(struct kimage *image)
 		 * Respective architecture needs to provide support for applying
 		 * relocations of type SHT_RELA/SHT_REL.
 		 */
-		if (sechdrs[i].sh_type == SHT_RELA)
-			ret = arch_kexec_apply_relocations_add(pi->ehdr,
-							       sechdrs, i);
-		else if (sechdrs[i].sh_type == SHT_REL)
-			ret = arch_kexec_apply_relocations(pi->ehdr,
-							   sechdrs, i);
+		if (relsec->sh_type == SHT_RELA)
+			ret = arch_kexec_apply_relocations_add(pi, section,
+							       relsec, symtab);
+		else if (relsec->sh_type == SHT_REL)
+			ret = arch_kexec_apply_relocations(pi, section,
+							   relsec, symtab);
 		if (ret)
 			return ret;
 	}
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 06/11] kexec_file: Split up __kexec_load_puragory
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (4 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations* Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 07/11] kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs Philipp Rudo
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

When inspecting __kexec_load_purgatory you find that it has two tasks

	1) setting up the kexec_buffer for the new kernel and,
	2) setting up pi->sechdrs for the final load address.

The two tasks are independent of each other. To improve readability split
up __kexec_load_purgatory into two functions, one for each task, and call
them directly from kexec_load_purgatory.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 kernel/kexec_file.c | 200 +++++++++++++++++++++++++++-------------------------
 1 file changed, 103 insertions(+), 97 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 80c7f658afc0..d1c3ec8dc6b1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -649,39 +649,97 @@ static int kexec_calculate_store_digests(struct kimage *image)
 	return ret;
 }
 
-/* Actually load purgatory. Lot of code taken from kexec-tools */
-static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
-				  unsigned long max, int top_down)
+/*
+ * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory.
+ * @pi:		Purgatory to be loaded.
+ * @kbuf:	Buffer to setup.
+ *
+ * Allocates the memory needed for the buffer. Caller is responsible to free
+ * the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
+				      struct kexec_buf *kbuf)
 {
-	struct purgatory_info *pi = &image->purgatory_info;
-	unsigned long align, bss_align, bss_sz, bss_pad;
-	unsigned long entry, load_addr, curr_load_addr, bss_addr, offset;
-	unsigned char *buf_addr, *src;
-	int i, ret = 0, entry_sidx = -1;
-	const Elf_Shdr *sechdrs_c;
-	Elf_Shdr *sechdrs = NULL;
-	struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
-				  .buf_min = min, .buf_max = max,
-				  .top_down = top_down };
+	const Elf_Shdr *sechdrs;
+	unsigned long bss_align;
+	unsigned long bss_sz;
+	unsigned long align;
+	int i, ret;
 
-	/*
-	 * sechdrs_c points to section headers in purgatory and are read
-	 * only. No modifications allowed.
-	 */
-	sechdrs_c = (void *)pi->ehdr + pi->ehdr->e_shoff;
+	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
+	bss_align = 1;
+	bss_sz = 0;
+
+	for (i = 0; i < pi->ehdr->e_shnum; i++) {
+		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+			continue;
+
+		align = sechdrs[i].sh_addralign;
+		if (sechdrs[i].sh_type != SHT_NOBITS) {
+			if (kbuf->buf_align < align)
+				kbuf->buf_align = align;
+			kbuf->bufsz = ALIGN(kbuf->bufsz, align);
+			kbuf->bufsz += sechdrs[i].sh_size;
+		} else {
+			if (bss_align < align)
+				bss_align = align;
+			bss_sz = ALIGN(bss_sz, align);
+			bss_sz += sechdrs[i].sh_size;
+		}
+	}
+	kbuf->bufsz = ALIGN(kbuf->bufsz, bss_align);
+	kbuf->memsz = kbuf->bufsz + bss_sz;
+	if (kbuf->buf_align < bss_align)
+		kbuf->buf_align = bss_align;
+
+	kbuf->buffer = vzalloc(kbuf->bufsz);
+	if (!kbuf->buffer)
+		return -ENOMEM;
+	pi->purgatory_buf = kbuf->buffer;
+
+	ret = kexec_add_buffer(kbuf);
+	if (ret)
+		goto out;
+	pi->purgatory_load_addr = kbuf->mem;
+
+	return 0;
+out:
+	vfree(pi->purgatory_buf);
+	pi->purgatory_buf = NULL;
+	return ret;
+}
+
+/*
+ * kexec_purgatory_setup_sechdrs - prepares the pi->sechdrs buffer.
+ * @pi:		Purgatory to be loaded.
+ * @kbuf:	Buffer prepared to store purgatory.
+ *
+ * Allocates the memory needed for the buffer. Caller is responsible to free
+ * the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
+					 struct kexec_buf *kbuf)
+{
+	unsigned long curr_load_addr;
+	unsigned long load_addr;
+	unsigned long bss_addr;
+	unsigned long offset;
+	unsigned char *buf_addr;
+	unsigned char *src;
+	Elf_Shdr *sechdrs;
+	int entry_sidx = -1;
+	int i;
 
-	/*
-	 * We can not modify sechdrs_c[] and its fields. It is read only.
-	 * Copy it over to a local copy where one can store some temporary
-	 * data and free it at the end. We need to modify ->sh_addr and
-	 * ->sh_offset fields to keep track of permanent and temporary
-	 * locations of sections.
-	 */
 	sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
 	if (!sechdrs)
 		return -ENOMEM;
-
-	memcpy(sechdrs, sechdrs_c, pi->ehdr->e_shnum * sizeof(Elf_Shdr));
+	memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff,
+	       pi->ehdr->e_shnum * sizeof(Elf_Shdr));
+	pi->sechdrs = sechdrs;
 
 	/*
 	 * We seem to have multiple copies of sections. First copy is which
@@ -709,7 +767,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 	 * Identify entry point section and make entry relative to section
 	 * start.
 	 */
-	entry = pi->ehdr->e_entry;
+	kbuf->image->start = pi->ehdr->e_entry;
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
 			continue;
@@ -722,63 +780,19 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 		    ((sechdrs[i].sh_addr + sechdrs[i].sh_size) >
 		     pi->ehdr->e_entry)) {
 			entry_sidx = i;
-			entry -= sechdrs[i].sh_addr;
+			kbuf->image->start -= sechdrs[i].sh_addr;
 			break;
 		}
 	}
 
-	/* Determine how much memory is needed to load relocatable object. */
-	bss_align = 1;
-	bss_sz = 0;
-
-	for (i = 0; i < pi->ehdr->e_shnum; i++) {
-		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
-			continue;
-
-		align = sechdrs[i].sh_addralign;
-		if (sechdrs[i].sh_type != SHT_NOBITS) {
-			if (kbuf.buf_align < align)
-				kbuf.buf_align = align;
-			kbuf.bufsz = ALIGN(kbuf.bufsz, align);
-			kbuf.bufsz += sechdrs[i].sh_size;
-		} else {
-			/* bss section */
-			if (bss_align < align)
-				bss_align = align;
-			bss_sz = ALIGN(bss_sz, align);
-			bss_sz += sechdrs[i].sh_size;
-		}
-	}
-
-	/* Determine the bss padding required to align bss properly */
-	bss_pad = 0;
-	if (kbuf.bufsz & (bss_align - 1))
-		bss_pad = bss_align - (kbuf.bufsz & (bss_align - 1));
-
-	kbuf.memsz = kbuf.bufsz + bss_pad + bss_sz;
-
-	/* Allocate buffer for purgatory */
-	kbuf.buffer = vzalloc(kbuf.bufsz);
-	if (!kbuf.buffer) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (kbuf.buf_align < bss_align)
-		kbuf.buf_align = bss_align;
-
-	/* Add buffer to segment list */
-	ret = kexec_add_buffer(&kbuf);
-	if (ret)
-		goto out;
-	pi->purgatory_load_addr = kbuf.mem;
-
 	/* Load SHF_ALLOC sections */
-	buf_addr = kbuf.buffer;
-	load_addr = curr_load_addr = pi->purgatory_load_addr;
-	bss_addr = load_addr + kbuf.bufsz + bss_pad;
+	buf_addr = kbuf->buffer;
+	load_addr = curr_load_addr = kbuf->mem;
+	bss_addr = load_addr + kbuf->bufsz;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
+		unsigned long align;
+
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
 			continue;
 
@@ -810,24 +824,9 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 
 	/* Update entry point based on load address of text section */
 	if (entry_sidx >= 0)
-		entry += sechdrs[entry_sidx].sh_addr;
-
-	/* Make kernel jump to purgatory after shutdown */
-	image->start = entry;
-
-	/* Used later to get/set symbol values */
-	pi->sechdrs = sechdrs;
+		kbuf->image->start += sechdrs[entry_sidx].sh_addr;
 
-	/*
-	 * Used later to identify which section is purgatory and skip it
-	 * from checksumming.
-	 */
-	pi->purgatory_buf = kbuf.buffer;
-	return ret;
-out:
-	vfree(sechdrs);
-	vfree(kbuf.buffer);
-	return ret;
+	return 0;
 }
 
 static int kexec_apply_relocations(struct kimage *image)
@@ -897,16 +896,23 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 {
 	struct purgatory_info *pi = &image->purgatory_info;
 	int ret;
+	struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
+				  .buf_min = min, .buf_max = max,
+				  .top_down = top_down };
 
 	if (kexec_purgatory_size <= 0)
 		return -EINVAL;
 
 	pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
 
-	ret = __kexec_load_purgatory(image, min, max, top_down);
+	ret = kexec_purgatory_setup_kbuf(pi, &kbuf);
 	if (ret)
 		return ret;
 
+	ret = kexec_purgatory_setup_sechdrs(pi, &kbuf);
+	if (ret)
+		goto out_free_kbuf;
+
 	ret = kexec_apply_relocations(image);
 	if (ret)
 		goto out;
@@ -916,7 +922,7 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 out:
 	vfree(pi->sechdrs);
 	pi->sechdrs = NULL;
-
+out_free_kbuf:
 	vfree(pi->purgatory_buf);
 	pi->purgatory_buf = NULL;
 	return ret;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 07/11] kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (5 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 06/11] kexec_file: Split up __kexec_load_puragory Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 08/11] kexec_file: Remove unneeded variables " Philipp Rudo
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

To update the entry point there is an extra loop over all section headers
although this can be done in the main loop. So move it there and eliminate
the extra loop and variable to store the 'entry section index'.

Also, in the main loop, move the usual case, i.e. non-bss section, out of
the extra if-block.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
 kernel/kexec_file.c | 76 +++++++++++++++++++++--------------------------------
 1 file changed, 30 insertions(+), 46 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index d1c3ec8dc6b1..4938f7aacd09 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -731,7 +731,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 	unsigned char *buf_addr;
 	unsigned char *src;
 	Elf_Shdr *sechdrs;
-	int entry_sidx = -1;
 	int i;
 
 	sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
@@ -763,32 +762,11 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 						sechdrs[i].sh_offset;
 	}
 
-	/*
-	 * Identify entry point section and make entry relative to section
-	 * start.
-	 */
-	kbuf->image->start = pi->ehdr->e_entry;
-	for (i = 0; i < pi->ehdr->e_shnum; i++) {
-		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
-			continue;
-
-		if (!(sechdrs[i].sh_flags & SHF_EXECINSTR))
-			continue;
-
-		/* Make entry section relative */
-		if (sechdrs[i].sh_addr <= pi->ehdr->e_entry &&
-		    ((sechdrs[i].sh_addr + sechdrs[i].sh_size) >
-		     pi->ehdr->e_entry)) {
-			entry_sidx = i;
-			kbuf->image->start -= sechdrs[i].sh_addr;
-			break;
-		}
-	}
-
 	/* Load SHF_ALLOC sections */
 	buf_addr = kbuf->buffer;
 	load_addr = curr_load_addr = kbuf->mem;
 	bss_addr = load_addr + kbuf->bufsz;
+	kbuf->image->start = pi->ehdr->e_entry;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
 		unsigned long align;
@@ -797,34 +775,40 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 			continue;
 
 		align = sechdrs[i].sh_addralign;
-		if (sechdrs[i].sh_type != SHT_NOBITS) {
-			curr_load_addr = ALIGN(curr_load_addr, align);
-			offset = curr_load_addr - load_addr;
-			/* We already modifed ->sh_offset to keep src addr */
-			src = (char *) sechdrs[i].sh_offset;
-			memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
-
-			/* Store load address and source address of section */
-			sechdrs[i].sh_addr = curr_load_addr;
-
-			/*
-			 * This section got copied to temporary buffer. Update
-			 * ->sh_offset accordingly.
-			 */
-			sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
-
-			/* Advance to the next address */
-			curr_load_addr += sechdrs[i].sh_size;
-		} else {
+
+		if (sechdrs[i].sh_type == SHT_NOBITS) {
 			bss_addr = ALIGN(bss_addr, align);
 			sechdrs[i].sh_addr = bss_addr;
 			bss_addr += sechdrs[i].sh_size;
+			continue;
+		}
+
+		curr_load_addr = ALIGN(curr_load_addr, align);
+		offset = curr_load_addr - load_addr;
+		/* We already modifed ->sh_offset to keep src addr */
+		src = (char *)sechdrs[i].sh_offset;
+		memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
+
+		if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
+		    pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
+		    pi->ehdr->e_entry < (sechdrs[i].sh_addr
+					 + sechdrs[i].sh_size)) {
+			kbuf->image->start -= sechdrs[i].sh_addr;
+			kbuf->image->start += curr_load_addr;
 		}
-	}
 
-	/* Update entry point based on load address of text section */
-	if (entry_sidx >= 0)
-		kbuf->image->start += sechdrs[entry_sidx].sh_addr;
+		/* Store load address and source address of section */
+		sechdrs[i].sh_addr = curr_load_addr;
+
+		/*
+		 * This section got copied to temporary buffer. Update
+		 * ->sh_offset accordingly.
+		 */
+		sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
+
+		/* Advance to the next address */
+		curr_load_addr += sechdrs[i].sh_size;
+	}
 
 	return 0;
 }
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 08/11] kexec_file: Remove unneeded variables in kexec_purgatory_setup_sechdrs
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (6 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 07/11] kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 09/11] kexec_file: Remove mis-use of sh_offset field during purgatory load Philipp Rudo
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

The main loop currently uses quite a lot of variables to update the section
headers. Some of them are unnecessary. So clean them up a little.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 kernel/kexec_file.c | 34 ++++++++++++----------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 4938f7aacd09..746b91e46e34 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -724,12 +724,8 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
 static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 					 struct kexec_buf *kbuf)
 {
-	unsigned long curr_load_addr;
-	unsigned long load_addr;
 	unsigned long bss_addr;
 	unsigned long offset;
-	unsigned char *buf_addr;
-	unsigned char *src;
 	Elf_Shdr *sechdrs;
 	int i;
 
@@ -762,20 +758,18 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 						sechdrs[i].sh_offset;
 	}
 
-	/* Load SHF_ALLOC sections */
-	buf_addr = kbuf->buffer;
-	load_addr = curr_load_addr = kbuf->mem;
-	bss_addr = load_addr + kbuf->bufsz;
+	offset = 0;
+	bss_addr = kbuf->mem + kbuf->bufsz;
 	kbuf->image->start = pi->ehdr->e_entry;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
 		unsigned long align;
+		void *src, *dst;
 
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
 			continue;
 
 		align = sechdrs[i].sh_addralign;
-
 		if (sechdrs[i].sh_type == SHT_NOBITS) {
 			bss_addr = ALIGN(bss_addr, align);
 			sechdrs[i].sh_addr = bss_addr;
@@ -783,31 +777,27 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 			continue;
 		}
 
-		curr_load_addr = ALIGN(curr_load_addr, align);
-		offset = curr_load_addr - load_addr;
-		/* We already modifed ->sh_offset to keep src addr */
-		src = (char *)sechdrs[i].sh_offset;
-		memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
-
+		offset = ALIGN(offset, align);
 		if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
 		    pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
 		    pi->ehdr->e_entry < (sechdrs[i].sh_addr
 					 + sechdrs[i].sh_size)) {
 			kbuf->image->start -= sechdrs[i].sh_addr;
-			kbuf->image->start += curr_load_addr;
+			kbuf->image->start += kbuf->mem + offset;
 		}
 
-		/* Store load address and source address of section */
-		sechdrs[i].sh_addr = curr_load_addr;
+		src = (void *)sechdrs[i].sh_offset;
+		dst = pi->purgatory_buf + offset;
+		memcpy(dst, src, sechdrs[i].sh_size);
+
+		sechdrs[i].sh_addr = kbuf->mem + offset;
 
 		/*
 		 * This section got copied to temporary buffer. Update
 		 * ->sh_offset accordingly.
 		 */
-		sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
-
-		/* Advance to the next address */
-		curr_load_addr += sechdrs[i].sh_size;
+		sechdrs[i].sh_offset = (unsigned long)dst;
+		offset += sechdrs[i].sh_size;
 	}
 
 	return 0;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 09/11] kexec_file: Remove mis-use of sh_offset field during purgatory load
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (7 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 08/11] kexec_file: Remove unneeded variables " Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 10/11] kexec_file: Allow archs to set purgatory load address Philipp Rudo
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

The current code uses the sh_offset field in purgatory_info->sechdrs to
store a pointer to the current load address of the section. Depending
whether the section will be loaded or not this is either a pointer into
purgatory_info->purgatory_buf or kexec_purgatory. This is not only a
violation of the ELF standard but also makes the code very hard to
understand as you cannot tell if the memory you are using is read-only or
not.

Remove this mis-use and store the offset of the section in
pugaroty_info->purgatory_buf in sh_offset.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
 kernel/kexec_file.c                | 37 +++++++------------------------------
 2 files changed, 13 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 51667c8b5c9b..41db74bdc88b 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -457,13 +457,15 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
 		 * rel[i].r_offset contains byte offset from beginning
 		 * of section to the storage unit affected.
 		 *
-		 * This is location to update (->sh_offset). This is temporary
-		 * buffer where section is currently loaded. This will finally
-		 * be loaded to a different address later, pointed to by
+		 * This is location to update. This is temporary buffer
+		 * where section is currently loaded. This will finally be
+		 * loaded to a different address later, pointed to by
 		 * ->sh_addr. kexec takes care of moving it
 		 *  (kexec_load_segment()).
 		 */
-		location = (void *)(section->sh_offset + rel[i].r_offset);
+		location = pi->purgatory_buf;
+		location += section->sh_offset;
+		location += rel[i].r_offset;
 
 		/* Final address of the location */
 		address = section->sh_addr + rel[i].r_offset;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 746b91e46e34..1478766c7754 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -729,6 +729,10 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 	Elf_Shdr *sechdrs;
 	int i;
 
+	/*
+	 * The section headers in kexec_purgatory are read-only. In order to
+	 * have them modifiable make a temporary copy.
+	 */
 	sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
 	if (!sechdrs)
 		return -ENOMEM;
@@ -736,28 +740,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 	       pi->ehdr->e_shnum * sizeof(Elf_Shdr));
 	pi->sechdrs = sechdrs;
 
-	/*
-	 * We seem to have multiple copies of sections. First copy is which
-	 * is embedded in kernel in read only section. Some of these sections
-	 * will be copied to a temporary buffer and relocated. And these
-	 * sections will finally be copied to their final destination at
-	 * segment load time.
-	 *
-	 * Use ->sh_offset to reflect section address in memory. It will
-	 * point to original read only copy if section is not allocatable.
-	 * Otherwise it will point to temporary copy which will be relocated.
-	 *
-	 * Use ->sh_addr to contain final address of the section where it
-	 * will go during execution time.
-	 */
-	for (i = 0; i < pi->ehdr->e_shnum; i++) {
-		if (sechdrs[i].sh_type == SHT_NOBITS)
-			continue;
-
-		sechdrs[i].sh_offset = (unsigned long)pi->ehdr +
-						sechdrs[i].sh_offset;
-	}
-
 	offset = 0;
 	bss_addr = kbuf->mem + kbuf->bufsz;
 	kbuf->image->start = pi->ehdr->e_entry;
@@ -786,17 +768,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
 			kbuf->image->start += kbuf->mem + offset;
 		}
 
-		src = (void *)sechdrs[i].sh_offset;
+		src = (void *)pi->ehdr + sechdrs[i].sh_offset;
 		dst = pi->purgatory_buf + offset;
 		memcpy(dst, src, sechdrs[i].sh_size);
 
 		sechdrs[i].sh_addr = kbuf->mem + offset;
-
-		/*
-		 * This section got copied to temporary buffer. Update
-		 * ->sh_offset accordingly.
-		 */
-		sechdrs[i].sh_offset = (unsigned long)dst;
+		sechdrs[i].sh_offset = offset;
 		offset += sechdrs[i].sh_size;
 	}
 
@@ -1006,7 +983,7 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
 		return -EINVAL;
 	}
 
-	sym_buf = (char *)sec->sh_offset + sym->st_value;
+	sym_buf = (char *)pi->purgatory_buf + sec->sh_offset + sym->st_value;
 
 	if (get_value)
 		memcpy((void *)buf, sym_buf, size);
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 10/11] kexec_file: Allow archs to set purgatory load address
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (8 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 09/11] kexec_file: Remove mis-use of sh_offset field during purgatory load Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 11:27 ` [PATCH v2 11/11] kexec_file: Move purgatories sha256 to common code Philipp Rudo
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

For s390 new kernels are loaded to fixed addresses in memory before they
are booted. With the current code this is a problem as it assumes the
kernel will be loaded to an 'arbitrary' address. In particular,
kexec_locate_mem_hole searches for a large enough memory region and sets
the load address (kexec_bufer->mem) to it.

Luckily there is a simple workaround for this problem. By returning 1 in
arch_kexec_walk_mem, kexec_locate_mem_hole is turned off. This allows the
architecture to set kbuf->mem by hand. While the trick works fine for the
kernel it does not for the purgatory as here the architectures don't have
access to its kexec_buffer.

Give architectures access to the purgatories kexec_buffer by changing
kexec_load_purgatory to take a pointer to it. With this change
architectures have access to the buffer and can edit it as they need.

A nice side effect of this change is that we can get rid of the
purgatory_info->purgatory_load_address field. As now the information stored
there can directly be accessed from kbuf->mem.

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
 arch/powerpc/kernel/kexec_elf_64.c |  9 +++++----
 arch/x86/kernel/kexec-bzimage64.c  |  8 ++++----
 include/linux/kexec.h              | 17 ++++++-----------
 kernel/kexec_file.c                | 29 ++++++++++++++++-------------
 4 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 9a42309b091a..82448c03502d 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -572,7 +572,7 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
 {
 	int ret;
 	unsigned int fdt_size;
-	unsigned long kernel_load_addr, purgatory_load_addr;
+	unsigned long kernel_load_addr;
 	unsigned long initrd_load_addr = 0, fdt_load_addr;
 	void *fdt;
 	const void *slave_code;
@@ -580,6 +580,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
 	struct elf_info elf_info;
 	struct kexec_buf kbuf = { .image = image, .buf_min = 0,
 				  .buf_max = ppc64_rma_size };
+	struct kexec_buf pbuf = { .image = image, .buf_min = 0,
+				  .buf_max = ppc64_rma_size, .top_down = true };
 
 	ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
 	if (ret)
@@ -591,14 +593,13 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
 
 	pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
 
-	ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true,
-				   &purgatory_load_addr);
+	ret = kexec_load_purgatory(image, &pbuf);
 	if (ret) {
 		pr_err("Loading purgatory failed.\n");
 		goto out;
 	}
 
-	pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+	pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
 
 	if (initrd != NULL) {
 		kbuf.buffer = initrd;
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index fb095ba0c02f..df183585928f 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -334,7 +334,6 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	unsigned long setup_header_size, params_cmdline_sz;
 	struct boot_params *params;
 	unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
-	unsigned long purgatory_load_addr;
 	struct bzimage64_data *ldata;
 	struct kexec_entry64_regs regs64;
 	void *stack;
@@ -342,6 +341,8 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
 	struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
 				  .top_down = true };
+	struct kexec_buf pbuf = { .image = image, .buf_min = MIN_PURGATORY_ADDR,
+				  .buf_max = ULONG_MAX, .top_down = true };
 
 	header = (struct setup_header *)(kernel + setup_hdr_offset);
 	setup_sects = header->setup_sects;
@@ -379,14 +380,13 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	 * Load purgatory. For 64bit entry point, purgatory  code can be
 	 * anywhere.
 	 */
-	ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1,
-				   &purgatory_load_addr);
+	ret = kexec_load_purgatory(image, &pbuf);
 	if (ret) {
 		pr_err("Loading purgatory failed\n");
 		return ERR_PTR(ret);
 	}
 
-	pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+	pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
 
 
 	/*
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index a757ec37775f..381362eb0f61 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -114,9 +114,6 @@ struct purgatory_info {
 	 * relocation. This memory can be freed post image load.
 	 */
 	void *purgatory_buf;
-
-	/* Address where purgatory is finally loaded and is executed from */
-	unsigned long purgatory_load_addr;
 };
 
 struct kimage;
@@ -166,6 +163,12 @@ struct kexec_buf {
 	bool top_down;
 };
 
+int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
+int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
+				   void *buf, unsigned int size,
+				   bool get_value);
+void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
+
 int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
 					    Elf_Shdr *section,
 					    const Elf_Shdr *relsec,
@@ -246,14 +249,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
 extern int kernel_kexec(void);
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
 						unsigned int order);
-extern int kexec_load_purgatory(struct kimage *image, unsigned long min,
-				unsigned long max, int top_down,
-				unsigned long *load_addr);
-extern int kexec_purgatory_get_set_symbol(struct kimage *image,
-					  const char *name, void *buf,
-					  unsigned int size, bool get_value);
-extern void *kexec_purgatory_get_symbol_addr(struct kimage *image,
-					     const char *name);
 extern void __crash_kexec(struct pt_regs *);
 extern void crash_kexec(struct pt_regs *);
 int kexec_should_crash(struct task_struct *);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 1478766c7754..97d5c946fa36 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -669,8 +669,8 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
 	int i, ret;
 
 	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
-	bss_align = 1;
-	bss_sz = 0;
+	kbuf->buf_align = bss_align = 1;
+	kbuf->bufsz = bss_sz = 0;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -702,7 +702,6 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
 	ret = kexec_add_buffer(kbuf);
 	if (ret)
 		goto out;
-	pi->purgatory_load_addr = kbuf->mem;
 
 	return 0;
 out:
@@ -840,27 +839,32 @@ static int kexec_apply_relocations(struct kimage *image)
 	return 0;
 }
 
-/* Load relocatable purgatory object and relocate it appropriately */
-int kexec_load_purgatory(struct kimage *image, unsigned long min,
-			 unsigned long max, int top_down,
-			 unsigned long *load_addr)
+/*
+ * kexec_load_purgatory - Load and relocate the purgatory object.
+ * @image:	Image to add the purgatory to.
+ * @kbuf:	Memory parameters to use.
+ *
+ * Allocates the memory needed for image->purgatory_info.sechdrs and
+ * image->purgatory_info.purgatory_buf/kbuf->buffer. Caller is responsible
+ * to free the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
 {
 	struct purgatory_info *pi = &image->purgatory_info;
 	int ret;
-	struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
-				  .buf_min = min, .buf_max = max,
-				  .top_down = top_down };
 
 	if (kexec_purgatory_size <= 0)
 		return -EINVAL;
 
 	pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
 
-	ret = kexec_purgatory_setup_kbuf(pi, &kbuf);
+	ret = kexec_purgatory_setup_kbuf(pi, kbuf);
 	if (ret)
 		return ret;
 
-	ret = kexec_purgatory_setup_sechdrs(pi, &kbuf);
+	ret = kexec_purgatory_setup_sechdrs(pi, kbuf);
 	if (ret)
 		goto out_free_kbuf;
 
@@ -868,7 +872,6 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
 	if (ret)
 		goto out;
 
-	*load_addr = pi->purgatory_load_addr;
 	return 0;
 out:
 	vfree(pi->sechdrs);
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 11/11] kexec_file: Move purgatories sha256 to common code
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (9 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 10/11] kexec_file: Allow archs to set purgatory load address Philipp Rudo
@ 2018-03-21 11:27 ` Philipp Rudo
  2018-03-21 23:00 ` [PATCH v2 00/11] kexec_file: Clean up purgatory load Andrew Morton
  2018-03-23  1:03 ` Dave Young
  12 siblings, 0 replies; 16+ messages in thread
From: Philipp Rudo @ 2018-03-21 11:27 UTC (permalink / raw)
  To: kexec, linux-s390
  Cc: linux-kernel, Eric Biederman, Vivek Goyal, Michael Ellerman,
	Thiago Jung Bauermann, Martin Schwidefsky, Heiko Carstens,
	Andrew Morton, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

The code to verify the new kernels sha digest is applicable for all
architectures. Move it to common code.

One problem is the string.c implementation on x86. Currently sha256
includes x86/boot/string.h which defines memcpy and memset to be gcc
builtins. By moving the sha256 implementation to common code and changing
the include to linux/string.h both functions are no longer defined. Thus
definitions have to be provided in x86/purgatory/string.c

Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com>
---
 arch/x86/purgatory/Makefile                    |  3 +++
 arch/x86/purgatory/purgatory.c                 |  2 +-
 arch/x86/purgatory/string.c                    | 12 ++++++++++++
 {arch/x86/purgatory => include/linux}/sha256.h | 11 ++++++++++-
 {arch/x86/purgatory => lib}/sha256.c           |  4 ++--
 5 files changed, 28 insertions(+), 4 deletions(-)
 rename {arch/x86/purgatory => include/linux}/sha256.h (62%)
 rename {arch/x86/purgatory => lib}/sha256.c (99%)

diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2f15a2ac4209..414eed6b5065 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -6,6 +6,9 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string
 targets += $(purgatory-y)
 PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
 
+$(obj)/sha256.o: $(srctree)/lib/sha256.c
+	$(call if_changed_rule,cc_o_c)
+
 LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
 targets += purgatory.ro
 
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c
index 470edad96bb9..025c34ac0d84 100644
--- a/arch/x86/purgatory/purgatory.c
+++ b/arch/x86/purgatory/purgatory.c
@@ -11,9 +11,9 @@
  */
 
 #include <linux/bug.h>
+#include <linux/sha256.h>
 #include <asm/purgatory.h>
 
-#include "sha256.h"
 #include "../boot/string.h"
 
 unsigned long purgatory_backup_dest __section(.kexec-purgatory);
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c
index d886b1fa36f0..795ca4f2cb3c 100644
--- a/arch/x86/purgatory/string.c
+++ b/arch/x86/purgatory/string.c
@@ -10,4 +10,16 @@
  * Version 2.  See the file COPYING for more details.
  */
 
+#include <linux/types.h>
+
 #include "../boot/string.c"
+
+void *memcpy(void *dst, const void *src, size_t len)
+{
+	return __builtin_memcpy(dst, src, len);
+}
+
+void *memset(void *dst, int c, size_t len)
+{
+	return __builtin_memset(dst, c, len);
+}
diff --git a/arch/x86/purgatory/sha256.h b/include/linux/sha256.h
similarity index 62%
rename from arch/x86/purgatory/sha256.h
rename to include/linux/sha256.h
index 2867d9825a57..244fe01a65fb 100644
--- a/arch/x86/purgatory/sha256.h
+++ b/include/linux/sha256.h
@@ -13,9 +13,18 @@
 #include <linux/types.h>
 #include <crypto/sha.h>
 
+/*
+ * Stand-alone implementation of the SHA256 algorithm. It is designed to
+ * have as little dependencies as possible so it can be used in the
+ * kexec_file purgatory. In other cases you should use the implementation in
+ * crypto/.
+ *
+ * For details see lib/sha256.c
+ */
+
 extern int sha256_init(struct sha256_state *sctx);
 extern int sha256_update(struct sha256_state *sctx, const u8 *input,
-				unsigned int length);
+			 unsigned int length);
 extern int sha256_final(struct sha256_state *sctx, u8 *hash);
 
 #endif /* SHA256_H */
diff --git a/arch/x86/purgatory/sha256.c b/lib/sha256.c
similarity index 99%
rename from arch/x86/purgatory/sha256.c
rename to lib/sha256.c
index 548ca675a14a..4400c832e2aa 100644
--- a/arch/x86/purgatory/sha256.c
+++ b/lib/sha256.c
@@ -16,9 +16,9 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/sha256.h>
+#include <linux/string.h>
 #include <asm/byteorder.h>
-#include "sha256.h"
-#include "../boot/string.h"
 
 static inline u32 Ch(u32 x, u32 y, u32 z)
 {
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 00/11] kexec_file: Clean up purgatory load
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (10 preceding siblings ...)
  2018-03-21 11:27 ` [PATCH v2 11/11] kexec_file: Move purgatories sha256 to common code Philipp Rudo
@ 2018-03-21 23:00 ` Andrew Morton
  2018-03-23  9:41   ` Philipp Rudo
  2018-03-23  1:03 ` Dave Young
  12 siblings, 1 reply; 16+ messages in thread
From: Andrew Morton @ 2018-03-21 23:00 UTC (permalink / raw)
  To: Philipp Rudo
  Cc: kexec, linux-s390, linux-kernel, Eric Biederman, Vivek Goyal,
	Michael Ellerman, Thiago Jung Bauermann, Martin Schwidefsky,
	Heiko Carstens, x86, Dave Young, AKASHI Takahiro, Ingo Molnar

On Wed, 21 Mar 2018 12:27:40 +0100 Philipp Rudo <prudo@linux.vnet.ibm.com> wrote:

> here is the updated patch set including Dave's comments.

There were some syntactic clashes with the "kexec_file, x86, powerpc:
refactoring for other architecutres" series.  Please check (in
linux-next) that I got it all correct and that both patch series are
functioning correctly.

I expect to send all this into Stephen for -next tomorrow.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 00/11] kexec_file: Clean up purgatory load
  2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
                   ` (11 preceding siblings ...)
  2018-03-21 23:00 ` [PATCH v2 00/11] kexec_file: Clean up purgatory load Andrew Morton
@ 2018-03-23  1:03 ` Dave Young
  12 siblings, 0 replies; 16+ messages in thread
From: Dave Young @ 2018-03-23  1:03 UTC (permalink / raw)
  To: Philipp Rudo
  Cc: kexec, linux-s390, linux-kernel, Eric Biederman, Vivek Goyal,
	Michael Ellerman, Thiago Jung Bauermann, Martin Schwidefsky,
	Heiko Carstens, Andrew Morton, x86, AKASHI Takahiro, Ingo Molnar

On 03/21/18 at 12:27pm, Philipp Rudo wrote:
> Hi everybody
> 
> here is the updated patch set including Dave's comments.
> 
> Changes v1 -> v2:
> 	* Fix missing memcpy and memset definition in x86 purgatory
> 	introduced by moving the sha256 implementation to common code.
> 	* Update subject of patches #7-9 to be more precise.
> 	* Add missing semicolon in patch #7 found by kbuild bot.
> 	* Fix compile warnings found by kbuild bot by moving all kexec_file
> 	specific function declarations into a 'ifdef CONFIG_KEXEC_FILE'
> 	block (patch #5 and #10).
> 
> Thanks
> Philipp
> 

Philipp, thanks for the V2, it looks good and works for me.

Can you rebase the series on top of AKASHI's patches which has been
taken by Andrew?

> ---
> 
> Hi everybody
> 
> following the discussion with Dave and AKASHI, here are the common code
> patches extracted from my recent patch set (Add kexec_file_load support to
> s390) [1]. The patches were extracted to allow upstream integration together
> with AKASHI's common code patches before the arch code gets adjusted to the
> new base.
> 
> The reason for this series is to prepare common code for adding
> kexec_file_load to s390 as well as cleaning up the mis-use of the sh_offset
> field during purgatory load. In detail this series contains:
> 
> Patch #1&2: Minor cleanups/fixes.
> 
> Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> depending on the section. With these patches the section address will be
> calculated verbosely and sh_offset will contain the offset of the section
> in the stripped purgatory binary (purgatory_buf).
> 
> Patch #10: Allows architectures to set the purgatory load address. This
> patch is important for s390 as the kernel and purgatory have to be loaded
> to fixed addresses. In current code this is impossible as the purgatory
> load is opaque to the architecture.
> 
> Patch #11: Moves x86 purgatories sha implementation to common lib/
> directory to allow reuse in other architectures.
> 
> The patches apply to v4.16-rc3. There are no changes compared to [1] (all
> requested changes only affected s390 code). Please note that I had to touch
> arch code for x86 and power a little. In theory this should not change the
> behavior but I don't have a way to test it. Cross-compiling with
> defconfig [2] works fine for both.
> 
> Thanks
> Philipp
> 
> [1] http://lists.infradead.org/pipermail/kexec/2018-February/019926.html
> [2] On x86 with the orc unwinder and stack validation turned off. objtool
>     SEGFAULTs on s390...
> 
> Philipp Rudo (11):
>   kexec_file: Silence compile warnings
>   kexec_file: Remove checks in kexec_purgatory_load
>   kexec_file: Make purgatory_info->ehdr const
>   kexec_file: Search symbols in read-only kexec_purgatory
>   kexec_file: Use read-only sections in arch_kexec_apply_relocations*
>   kexec_file: Split up __kexec_load_puragory
>   kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs
>   kexec_file: Remove unneeded variables in kexec_purgatory_setup_sechdrs
>   kexec_file: Remove mis-use of sh_offset field during purgatory load
>   kexec_file: Allow archs to set purgatory load address
>   kexec_file: Move purgatories sha256 to common code
> 
>  arch/powerpc/kernel/kexec_elf_64.c             |   9 +-
>  arch/x86/kernel/kexec-bzimage64.c              |   8 +-
>  arch/x86/kernel/machine_kexec_64.c             |  66 ++---
>  arch/x86/purgatory/Makefile                    |   3 +
>  arch/x86/purgatory/purgatory.c                 |   2 +-
>  arch/x86/purgatory/string.c                    |  12 +
>  include/linux/kexec.h                          |  49 ++--
>  {arch/x86/purgatory => include/linux}/sha256.h |  11 +-
>  kernel/kexec_file.c                            | 379 ++++++++++++-------------
>  {arch/x86/purgatory => lib}/sha256.c           |   4 +-
>  10 files changed, 267 insertions(+), 276 deletions(-)
>  rename {arch/x86/purgatory => include/linux}/sha256.h (62%)
>  rename {arch/x86/purgatory => lib}/sha256.c (99%)
> 
> -- 
> 2.13.5
> 

Thanks
Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 00/11] kexec_file: Clean up purgatory load
  2018-03-21 23:00 ` [PATCH v2 00/11] kexec_file: Clean up purgatory load Andrew Morton
@ 2018-03-23  9:41   ` Philipp Rudo
  2018-04-10  6:59     ` Dave Young
  0 siblings, 1 reply; 16+ messages in thread
From: Philipp Rudo @ 2018-03-23  9:41 UTC (permalink / raw)
  To: Andrew Morton, Dave Young
  Cc: kexec, linux-s390, linux-kernel, Eric Biederman, Vivek Goyal,
	Michael Ellerman, Thiago Jung Bauermann, Martin Schwidefsky,
	Heiko Carstens, x86, AKASHI Takahiro, Ingo Molnar

Hi Andrew,
Hi Dave,

i checked out linux-next with the patches and it looks good to me. Also made a
quick test and everything works fine.

Thanks very much to both of you
Philipp


On Wed, 21 Mar 2018 16:00:42 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:

> On Wed, 21 Mar 2018 12:27:40 +0100 Philipp Rudo <prudo@linux.vnet.ibm.com> wrote:
> 
> > here is the updated patch set including Dave's comments.  
> 
> There were some syntactic clashes with the "kexec_file, x86, powerpc:
> refactoring for other architecutres" series.  Please check (in
> linux-next) that I got it all correct and that both patch series are
> functioning correctly.
> 
> I expect to send all this into Stephen for -next tomorrow.
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 00/11] kexec_file: Clean up purgatory load
  2018-03-23  9:41   ` Philipp Rudo
@ 2018-04-10  6:59     ` Dave Young
  0 siblings, 0 replies; 16+ messages in thread
From: Dave Young @ 2018-04-10  6:59 UTC (permalink / raw)
  To: Philipp Rudo
  Cc: Andrew Morton, linux-s390, Heiko Carstens, AKASHI Takahiro,
	Michael Ellerman, x86, kexec, linux-kernel, Martin Schwidefsky,
	Eric Biederman, Thiago Jung Bauermann, Ingo Molnar, Vivek Goyal

On 03/23/18 at 10:41am, Philipp Rudo wrote:
> Hi Andrew,
> Hi Dave,
> 
> i checked out linux-next with the patches and it looks good to me. Also made a
> quick test and everything works fine.

Thank you!  Not sure if it is late about an ack :)

Anyway, for the series:
Acked-by: Dave Young <dyoung@redhat.com>

Thanks
Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-04-10  6:59 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-21 11:27 [PATCH v2 00/11] kexec_file: Clean up purgatory load Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 01/11] kexec_file: Silence compile warnings Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 02/11] kexec_file: Remove checks in kexec_purgatory_load Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 03/11] kexec_file: Make purgatory_info->ehdr const Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 04/11] kexec_file: Search symbols in read-only kexec_purgatory Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations* Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 06/11] kexec_file: Split up __kexec_load_puragory Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 07/11] kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 08/11] kexec_file: Remove unneeded variables " Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 09/11] kexec_file: Remove mis-use of sh_offset field during purgatory load Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 10/11] kexec_file: Allow archs to set purgatory load address Philipp Rudo
2018-03-21 11:27 ` [PATCH v2 11/11] kexec_file: Move purgatories sha256 to common code Philipp Rudo
2018-03-21 23:00 ` [PATCH v2 00/11] kexec_file: Clean up purgatory load Andrew Morton
2018-03-23  9:41   ` Philipp Rudo
2018-04-10  6:59     ` Dave Young
2018-03-23  1:03 ` Dave Young

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).