2018-02-26 16:12:23

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 00/11] kexec_file: Clean up purgatory load


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: Simplify kexec_purgatory_setup_sechdrs 1
kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
kexec_file: Remove mis-use of sh_offset field
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 +-
include/linux/kexec.h | 38 +--
{arch/x86/purgatory => include/linux}/sha256.h | 10 +-
kernel/kexec_file.c | 375 ++++++++++++-------------
{arch/x86/purgatory => lib}/sha256.c | 4 +-
9 files changed, 244 insertions(+), 271 deletions(-)
rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
rename {arch/x86/purgatory => lib}/sha256.c (99%)

--
2.13.5



2018-02-26 15:30:47

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 02/11] kexec_file: Remove checks in kexec_purgatory_load

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 <[email protected]>
---
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


2018-02-26 15:31:06

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 03/11] kexec_file: Make purgatory_info->ehdr const

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 <[email protected]>
---
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


2018-02-26 15:33:05

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 07/11] kexec_file: Simplify kexec_purgatory_setup_sechdrs 1

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 <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
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..bb31a3b627c2 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


2018-02-26 15:42:14

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 08/11] kexec_file: Simplify kexec_purgatory_setup_sechdrs 2

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 <[email protected]>
---
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 bb31a3b627c2..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


2018-02-26 15:45:32

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations*

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 <[email protected]>
---
arch/x86/kernel/machine_kexec_64.c | 56 ++++++++++++---------------------
include/linux/kexec.h | 12 +++++---
kernel/kexec_file.c | 63 +++++++++++++++++++++++++-------------
3 files changed, 70 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..f15446be0e25 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -290,10 +290,14 @@ 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);
+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);
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


2018-02-26 16:10:51

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 10/11] kexec_file: Allow archs to set purgatory load address

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 <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
arch/powerpc/kernel/kexec_elf_64.c | 9 +++++----
arch/x86/kernel/kexec-bzimage64.c | 8 ++++----
include/linux/kexec.h | 7 +------
kernel/kexec_file.c | 29 ++++++++++++++++-------------
4 files changed, 26 insertions(+), 27 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 f15446be0e25..1cd9c5f49859 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;
@@ -237,9 +234,7 @@ 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_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
extern int kexec_purgatory_get_set_symbol(struct kimage *image,
const char *name, void *buf,
unsigned int size, bool get_value);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 25b44d1a664a..d69d1bf9e7a2 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:
@@ -836,27 +835,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;

@@ -864,7 +868,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


2018-02-26 16:15:16

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 09/11] kexec_file: Remove mis-use of sh_offset field

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 <[email protected]>
---
arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
kernel/kexec_file.c | 33 +++------------------------------
2 files changed, 9 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..25b44d1a664a 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -736,28 +736,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 +764,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 +979,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


2018-02-26 16:23:42

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 06/11] kexec_file: Split up __kexec_load_puragory

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 <[email protected]>
---
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


2018-02-26 16:40:50

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 04/11] kexec_file: Search symbols in read-only kexec_purgatory

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 <[email protected]>
---
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


2018-02-26 16:43:51

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 11/11] kexec_file: Move purgatories sha256 to common code

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

Signed-off-by: Philipp Rudo <[email protected]>
---
arch/x86/purgatory/Makefile | 3 +++
arch/x86/purgatory/purgatory.c | 2 +-
{arch/x86/purgatory => include/linux}/sha256.h | 10 +++++++++-
{arch/x86/purgatory => lib}/sha256.c | 4 ++--
4 files changed, 15 insertions(+), 4 deletions(-)
rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
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/sha256.h b/include/linux/sha256.h
similarity index 63%
rename from arch/x86/purgatory/sha256.h
rename to include/linux/sha256.h
index 2867d9825a57..43a20ac33688 100644
--- a/arch/x86/purgatory/sha256.h
+++ b/include/linux/sha256.h
@@ -13,9 +13,17 @@
#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


2018-02-26 16:58:20

by Philipp Rudo

[permalink] [raw]
Subject: [PATCH 01/11] kexec_file: Silence compile warnings

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 <[email protected]>
---
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


2018-02-28 15:40:47

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations*

Hi Philipp,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.16-rc3 next-20180228]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538
config: i386-randconfig-a0-201808 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All warnings (new ones prefixed by >>):

In file included from include/linux/crash_dump.h:5:0,
from drivers/scsi/aacraid/commsup.c:36:
>> include/linux/kexec.h:296:10: warning: 'struct purgatory_info' declared inside parameter list
const Elf_Shdr *symtab);
^
>> include/linux/kexec.h:296:10: warning: its scope is only this definition or declaration, which is probably not what you want
include/linux/kexec.h:300:6: warning: 'struct purgatory_info' declared inside parameter list
const Elf_Shdr *symtab);
^

vim +296 include/linux/kexec.h

286
287 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
288 unsigned long buf_len);
289 void * __weak arch_kexec_kernel_image_load(struct kimage *image);
290 int __weak arch_kimage_file_post_load_cleanup(struct kimage *image);
291 int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
292 unsigned long buf_len);
293 int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
294 Elf_Shdr *section,
295 const Elf_Shdr *relsec,
> 296 const Elf_Shdr *symtab);
297 int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
298 Elf_Shdr *section,
299 const Elf_Shdr *relsec,
300 const Elf_Shdr *symtab);
301 void arch_kexec_protect_crashkres(void);
302 void arch_kexec_unprotect_crashkres(void);
303

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (2.20 kB)
.config.gz (29.08 kB)
Download all attachments

2018-02-28 15:53:55

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 10/11] kexec_file: Allow archs to set purgatory load address

Hi Philipp,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.16-rc3 next-20180228]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538
config: x86_64-randconfig-x015-201808 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All warnings (new ones prefixed by >>):

In file included from arch/x86/kernel/traps.c:30:0:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
Cyclomatic Complexity 1 include/linux/percpu-defs.h:__this_cpu_preempt_check
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 4 include/linux/string.h:memmove
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:paravirt_get_debugreg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:set_debugreg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:read_cr0
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:write_cr0
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_disable
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_enable
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:user_mode
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:v8086_mode
Cyclomatic Complexity 1 include/asm-generic/ptrace.h:instruction_pointer
Cyclomatic Complexity 1 arch/x86/include/asm/processor.h:current_top_of_stack
Cyclomatic Complexity 1 arch/x86/include/asm/processor.h:on_thread_stack
Cyclomatic Complexity 1 include/linux/thread_info.h:set_ti_thread_flag
Cyclomatic Complexity 1 include/linux/thread_info.h:clear_ti_thread_flag
Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_add
Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_sub
Cyclomatic Complexity 1 include/linux/sched.h:task_pid_nr
Cyclomatic Complexity 1 include/linux/sched.h:task_thread_info
Cyclomatic Complexity 1 include/linux/sched.h:set_tsk_thread_flag
Cyclomatic Complexity 1 include/linux/sched.h:clear_tsk_thread_flag
Cyclomatic Complexity 1 arch/x86/include/asm/debugreg.h:debug_stack_usage_inc
Cyclomatic Complexity 1 arch/x86/include/asm/debugreg.h:debug_stack_usage_dec
Cyclomatic Complexity 3 arch/x86/include/asm/traps.h:get_si_code
Cyclomatic Complexity 1 arch/x86/include/asm/vm86.h:handle_vm86_trap
Cyclomatic Complexity 1 arch/x86/include/asm/umip.h:fixup_umip_exception
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:cond_local_irq_enable
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:cond_local_irq_disable
Cyclomatic Complexity 4 arch/x86/kernel/traps.c:fill_trap_info
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:is_sysenter_singlestep
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:do_trap_no_signal
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:do_trap
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:math_error
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:ist_enter
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:ist_exit
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:ist_begin_non_atomic
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:ist_end_non_atomic
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:is_valid_bugaddr
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:fixup_bug
Cyclomatic Complexity 4 arch/x86/kernel/traps.c:do_error_trap
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_divide_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_overflow
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_invalid_op
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_coprocessor_segment_overrun
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_invalid_TSS
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_segment_not_present
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_stack_segment
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_alignment_check
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_double_fault
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_bounds
Cyclomatic Complexity 11 arch/x86/kernel/traps.c:do_general_protection
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_int3
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:sync_regs
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:fixup_bad_iret
Cyclomatic Complexity 16 arch/x86/kernel/traps.c:do_debug
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_coprocessor_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_simd_coprocessor_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_spurious_interrupt_bug
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_device_not_available
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:trap_init
--
In file included from arch/x86/kernel/dumpstack_64.c:14:0:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:user_mode
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack_64.c:in_irq_stack
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack_64.c:in_exception_stack
Cyclomatic Complexity 5 arch/x86/kernel/dumpstack_64.c:stack_type_name
Cyclomatic Complexity 11 arch/x86/kernel/dumpstack_64.c:get_stack_info
Cyclomatic Complexity 8 arch/x86/kernel/dumpstack_64.c:show_regs
--
In file included from arch/x86/kernel/dumpstack.c:16:0:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size_nocheck
Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
Cyclomatic Complexity 2 include/linux/printk.h:console_verbose
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:kernel_stack_pointer
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_read
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_cmpxchg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_save_flags
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_restore
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_disable
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_save
Cyclomatic Complexity 1 arch/x86/include/asm/preempt.h:preempt_count
Cyclomatic Complexity 3 include/asm-generic/qspinlock.h:queued_spin_trylock
Cyclomatic Complexity 2 include/asm-generic/qspinlock.h:queued_spin_lock
Cyclomatic Complexity 1 include/linux/mm.h:debug_pagealloc_enabled
Cyclomatic Complexity 1 include/linux/module.h:print_modules
Cyclomatic Complexity 1 include/linux/ftrace.h:ftrace_graph_ret_addr
Cyclomatic Complexity 1 include/linux/sched/task_stack.h:task_stack_page
Cyclomatic Complexity 5 arch/x86/include/asm/stacktrace.h:on_stack
Cyclomatic Complexity 1 arch/x86/include/asm/unwind.h:unwind_done
Cyclomatic Complexity 3 arch/x86/include/asm/unwind.h:unwind_get_entry_regs
Cyclomatic Complexity 1 arch/x86/include/asm/cpu_entry_area.h:cpu_entry_stack
Cyclomatic Complexity 3 arch/x86/include/asm/stacktrace.h:get_stack_pointer
Cyclomatic Complexity 2 arch/x86/include/asm/unwind.h:unwind_start
Cyclomatic Complexity 1 include/linux/nmi.h:touch_nmi_watchdog
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:printk_stack_address
Cyclomatic Complexity 2 arch/x86/include/asm/qspinlock.h:native_queued_spin_unlock
Cyclomatic Complexity 1 arch/x86/include/asm/qspinlock.h:queued_spin_unlock
Cyclomatic Complexity 1 include/linux/kernel.h:kstrtoul
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:code_bytes_setup
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:in_task_stack
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:in_entry_stack
Cyclomatic Complexity 1 arch/x86/kernel/dumpstack.c:show_iret_regs
Cyclomatic Complexity 5 arch/x86/kernel/dumpstack.c:show_regs_if_on_stack
Cyclomatic Complexity 16 arch/x86/kernel/dumpstack.c:show_trace_log_lvl
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:show_stack
Cyclomatic Complexity 1 arch/x86/kernel/dumpstack.c:show_stack_regs
Cyclomatic Complexity 3 arch/x86/kernel/dumpstack.c:oops_begin
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:oops_end
Cyclomatic Complexity 3 arch/x86/kernel/dumpstack.c:__die
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:die
--
In file included from arch/x86/kernel/setup.c:45:0:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
Cyclomatic Complexity 1 arch/x86/include/asm/kaslr.h:kernel_randomize_memory
Cyclomatic Complexity 1 arch/x86/include/asm/page_types.h:get_max_mapped
Cyclomatic Complexity 1 include/linux/string.h:strnlen
Cyclomatic Complexity 4 include/linux/string.h:strlen
Cyclomatic Complexity 6 include/linux/string.h:strlcpy
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 1 arch/x86/include/asm/special_insns.h:native_read_cr4
Cyclomatic Complexity 1 arch/x86/include/asm/special_insns.h:__read_cr4
Cyclomatic Complexity 1 arch/x86/include/asm/mpspec.h:get_smp_config
Cyclomatic Complexity 1 arch/x86/include/asm/mpspec.h:find_smp_config
Cyclomatic Complexity 1 arch/x86/include/asm/numa.h:init_cpu_to_node
Cyclomatic Complexity 1 arch/x86/include/asm/apic.h:generic_apic_probe
Cyclomatic Complexity 1 arch/x86/include/asm/apic.h:check_x2apic
Cyclomatic Complexity 1 include/linux/kdev_t.h:old_decode_dev
Cyclomatic Complexity 1 include/linux/sfi.h:sfi_init
Cyclomatic Complexity 1 include/linux/efi.h:efi_esrt_init
Cyclomatic Complexity 1 include/linux/efi.h:efi_fake_memmap
Cyclomatic Complexity 1 include/linux/efi.h:efi_enabled
Cyclomatic Complexity 1 include/linux/iscsi_ibft.h:find_ibft_region
Cyclomatic Complexity 1 include/linux/dma-contiguous.h:dma_contiguous_reserve
Cyclomatic Complexity 1 include/linux/usb/xhci-dbgp.h:early_xdbc_setup_hardware
Cyclomatic Complexity 1 include/linux/usb/xhci-dbgp.h:early_xdbc_register_console
Cyclomatic Complexity 1 arch/x86/include/asm/mtrr.h:mtrr_trim_uncached_memory
Cyclomatic Complexity 1 arch/x86/include/asm/setup.h:kaslr_enabled
Cyclomatic Complexity 1 arch/x86/include/asm/setup.h:kaslr_offset
Cyclomatic Complexity 1 arch/x86/include/asm/efi.h:parse_efi_setup
Cyclomatic Complexity 1 arch/x86/include/asm/kasan.h:kasan_init
Cyclomatic Complexity 1 arch/x86/include/asm/gart.h:early_gart_iommu_check
Cyclomatic Complexity 1 arch/x86/include/asm/mpx.h:mpx_mm_init
Cyclomatic Complexity 1 arch/x86/include/asm/mmu_context.h:vma_pkey
Cyclomatic Complexity 1 arch/x86/include/asm/olpc_ofw.h:olpc_ofw_detect
Cyclomatic Complexity 1 arch/x86/include/asm/olpc_ofw.h:setup_olpc_ofw_pgd
Cyclomatic Complexity 1 arch/x86/include/asm/prom.h:add_dtb
Cyclomatic Complexity 1 arch/x86/include/asm/prom.h:x86_dtb_init
Cyclomatic Complexity 1 arch/x86/include/asm/unwind.h:unwind_init
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:copy_edd
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:get_ramdisk_image
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:get_ramdisk_size
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:parse_reservelow
Cyclomatic Complexity 3 arch/x86/kernel/setup.c:early_reserve_initrd
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_ibft_region
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_brk
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_low_memory_range
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:dump_kernel_offset
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:memblock_x86_reserve_range_setup_data
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:parse_setup_data
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:e820_add_kernel_range
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_bios_range
Cyclomatic Complexity 1 arch/x86/include/asm/mtrr.h:mtrr_bp_init
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:snb_gfx_workaround_needed
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:trim_snb_memory
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_platform_memory_ranges
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:relocate_initrd
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:reserve_initrd
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:reserve_crashkernel_low
Cyclomatic Complexity 12 arch/x86/kernel/setup.c:reserve_crashkernel
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:register_kernel_offset_dumper
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:__brk_reservation_fn_dmi_alloc__
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:extend_brk
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_standard_io_resources
Cyclomatic Complexity 14 arch/x86/kernel/setup.c:setup_arch
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:arch_show_smap
--
In file included from include/linux/crash_dump.h:5:0,
from arch/x86/kernel/e820.c:11:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
Cyclomatic Complexity 1 include/linux/printk.h:early_printk
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 4 include/linux/string.h:memcpy
Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
Cyclomatic Complexity 68 include/linux/slab.h:kmalloc_large
Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
Cyclomatic Complexity 1 include/linux/suspend.h:register_nosave_region
Cyclomatic Complexity 1 include/linux/firmware-map.h:firmware_map_add_early
Cyclomatic Complexity 8 arch/x86/kernel/e820.c:__e820__mapped_all
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:cpcompare
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820_search_gap
Cyclomatic Complexity 8 arch/x86/kernel/e820.c:e820_type_to_string
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820_type_to_iomem_type
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820_type_to_iores_desc
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:do_mark_busy
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:ram_alignment
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:__e820__range_add
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820_print_type
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820_end_pfn
Cyclomatic Complexity 10 arch/x86/kernel/e820.c:__e820__range_update
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_update_kexec
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__register_nvs_regions
Cyclomatic Complexity 0 arch/x86/kernel/e820.c:early_panic
Cyclomatic Complexity 2 include/linux/memblock.h:memblock_dump_all
Cyclomatic Complexity 6 arch/x86/kernel/e820.c:e820__mapped_any
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__mapped_all
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__get_entry_type
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_add
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:__append_e820_table
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:append_e820_table
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__print_table
Cyclomatic Complexity 18 arch/x86/kernel/e820.c:e820__update_table
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__update_table_kexec
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_update
Cyclomatic Complexity 12 arch/x86/kernel/e820.c:e820__range_remove
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:parse_memopt
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__update_table_print
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__setup_pci_gap
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__reallocate_tables
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__memory_setup_extended
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820__register_nosave_regions
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__memblock_alloc_reserved
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__end_of_ram_pfn
Cyclomatic Complexity 9 arch/x86/kernel/e820.c:parse_memmap_one
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:parse_memmap_opt
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__end_of_low_ram_pfn
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__reserve_setup_data
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__finish_early_params
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:e820__reserve_resources
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820__reserve_resources_late
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__memory_setup_default
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__memory_setup
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__memblock_setup
--
In file included from arch/x86/kernel/setup_percpu.c:9:0:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list will not be visible outside of this definition or declaration
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^~~~~~~~~
include/linux/kexec.h:288:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:292:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 2 arch/x86/include/asm/page_64.h:__phys_addr_nodebug
Cyclomatic Complexity 1 arch/x86/include/asm/topology.h:setup_node_to_cpumask_map
Cyclomatic Complexity 1 arch/x86/include/asm/stackprotector.h:setup_stack_canary_segment
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:pcpu_cpu_distance
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:setup_percpu_segment
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:pcpup_populate_pte
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:pcpu_fc_free
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:pcpu_alloc_bootmem
Cyclomatic Complexity 1 arch/x86/kernel/setup_percpu.c:pcpu_fc_alloc
Cyclomatic Complexity 6 arch/x86/kernel/setup_percpu.c:setup_per_cpu_areas
..

vim +237 include/linux/kexec.h

225
226 /* kexec interface functions */
227 extern void machine_kexec(struct kimage *image);
228 extern int machine_kexec_prepare(struct kimage *image);
229 extern void machine_kexec_cleanup(struct kimage *image);
230 extern asmlinkage long sys_kexec_load(unsigned long entry,
231 unsigned long nr_segments,
232 struct kexec_segment __user *segments,
233 unsigned long flags);
234 extern int kernel_kexec(void);
235 extern struct page *kimage_alloc_control_pages(struct kimage *image,
236 unsigned int order);
> 237 extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
238 extern int kexec_purgatory_get_set_symbol(struct kimage *image,
239 const char *name, void *buf,
240 unsigned int size, bool get_value);
241 extern void *kexec_purgatory_get_symbol_addr(struct kimage *image,
242 const char *name);
243 extern void __crash_kexec(struct pt_regs *);
244 extern void crash_kexec(struct pt_regs *);
245 int kexec_should_crash(struct task_struct *);
246 int kexec_crash_loaded(void);
247 void crash_save_cpu(struct pt_regs *regs, int cpu);
248 extern int kimage_crash_copy_vmcoreinfo(struct kimage *image);
249

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (25.05 kB)
.config.gz (23.62 kB)
Download all attachments

2018-02-28 16:34:48

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 05/11] kexec_file: Use read-only sections in arch_kexec_apply_relocations*

Hi Philipp,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.16-rc3 next-20180228]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538
config: x86_64-randconfig-x015-201808 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All warnings (new ones prefixed by >>):

In file included from init/initramfs.c:527:0:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
Cyclomatic Complexity 1 include/linux/list.h:__list_del
Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
Cyclomatic Complexity 1 include/linux/string.h:strnlen
Cyclomatic Complexity 4 include/linux/string.h:strlen
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 4 include/linux/string.h:memcpy
Cyclomatic Complexity 4 include/linux/string.h:memcmp
Cyclomatic Complexity 2 include/linux/string.h:strcpy
Cyclomatic Complexity 1 include/linux/kdev_t.h:new_encode_dev
Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
Cyclomatic Complexity 68 include/linux/slab.h:kmalloc_large
Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
Cyclomatic Complexity 2 init/initramfs.c:error
Cyclomatic Complexity 1 init/initramfs.c:hash
Cyclomatic Complexity 1 init/initramfs.c:eat
Cyclomatic Complexity 2 init/initramfs.c:read_into
Cyclomatic Complexity 1 init/initramfs.c:do_start
Cyclomatic Complexity 3 init/initramfs.c:do_collect
Cyclomatic Complexity 2 init/initramfs.c:do_skip
Cyclomatic Complexity 5 init/initramfs.c:do_reset
Cyclomatic Complexity 2 init/initramfs.c:write_buffer
Cyclomatic Complexity 6 init/initramfs.c:flush_buffer
Cyclomatic Complexity 2 init/initramfs.c:retain_initrd_param
Cyclomatic Complexity 6 init/initramfs.c:find_link
Cyclomatic Complexity 3 init/initramfs.c:free_hash
Cyclomatic Complexity 1 include/linux/fs.h:vfs_lstat
Cyclomatic Complexity 4 init/initramfs.c:clean_path
Cyclomatic Complexity 1 init/initramfs.c:do_utime
Cyclomatic Complexity 1 init/initramfs.c:do_symlink
Cyclomatic Complexity 6 init/initramfs.c:xwrite
Cyclomatic Complexity 4 init/initramfs.c:do_copy
Cyclomatic Complexity 2 include/linux/list.h:__list_add
Cyclomatic Complexity 1 include/linux/list.h:list_add
Cyclomatic Complexity 1 init/initramfs.c:dir_add
Cyclomatic Complexity 4 init/initramfs.c:maybe_link
Cyclomatic Complexity 12 init/initramfs.c:do_name
Cyclomatic Complexity 2 init/initramfs.c:parse_header
Cyclomatic Complexity 8 init/initramfs.c:do_header
Cyclomatic Complexity 2 include/linux/list.h:__list_del_entry
Cyclomatic Complexity 1 include/linux/list.h:list_del
Cyclomatic Complexity 5 init/initramfs.c:dir_utime
Cyclomatic Complexity 14 init/initramfs.c:unpack_to_rootfs
Cyclomatic Complexity 6 init/initramfs.c:free_initrd
Cyclomatic Complexity 3 init/initramfs.c:populate_rootfs
--
In file included from arch/x86/kernel/traps.c:30:0:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
Cyclomatic Complexity 1 include/linux/percpu-defs.h:__this_cpu_preempt_check
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 4 include/linux/string.h:memmove
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:paravirt_get_debugreg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:set_debugreg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:read_cr0
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:write_cr0
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_disable
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_enable
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:user_mode
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:v8086_mode
Cyclomatic Complexity 1 include/asm-generic/ptrace.h:instruction_pointer
Cyclomatic Complexity 1 arch/x86/include/asm/processor.h:current_top_of_stack
Cyclomatic Complexity 1 arch/x86/include/asm/processor.h:on_thread_stack
Cyclomatic Complexity 1 include/linux/thread_info.h:set_ti_thread_flag
Cyclomatic Complexity 1 include/linux/thread_info.h:clear_ti_thread_flag
Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_add
Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_sub
Cyclomatic Complexity 1 include/linux/sched.h:task_pid_nr
Cyclomatic Complexity 1 include/linux/sched.h:task_thread_info
Cyclomatic Complexity 1 include/linux/sched.h:set_tsk_thread_flag
Cyclomatic Complexity 1 include/linux/sched.h:clear_tsk_thread_flag
Cyclomatic Complexity 1 arch/x86/include/asm/debugreg.h:debug_stack_usage_inc
Cyclomatic Complexity 1 arch/x86/include/asm/debugreg.h:debug_stack_usage_dec
Cyclomatic Complexity 3 arch/x86/include/asm/traps.h:get_si_code
Cyclomatic Complexity 1 arch/x86/include/asm/vm86.h:handle_vm86_trap
Cyclomatic Complexity 1 arch/x86/include/asm/umip.h:fixup_umip_exception
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:cond_local_irq_enable
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:cond_local_irq_disable
Cyclomatic Complexity 4 arch/x86/kernel/traps.c:fill_trap_info
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:is_sysenter_singlestep
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:do_trap_no_signal
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:do_trap
Cyclomatic Complexity 6 arch/x86/kernel/traps.c:math_error
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:ist_enter
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:ist_exit
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:ist_begin_non_atomic
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:ist_end_non_atomic
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:is_valid_bugaddr
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:fixup_bug
Cyclomatic Complexity 4 arch/x86/kernel/traps.c:do_error_trap
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_divide_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_overflow
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_invalid_op
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_coprocessor_segment_overrun
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_invalid_TSS
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_segment_not_present
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_stack_segment
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_alignment_check
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_double_fault
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_bounds
Cyclomatic Complexity 11 arch/x86/kernel/traps.c:do_general_protection
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_int3
Cyclomatic Complexity 2 arch/x86/kernel/traps.c:sync_regs
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:fixup_bad_iret
Cyclomatic Complexity 16 arch/x86/kernel/traps.c:do_debug
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_coprocessor_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_simd_coprocessor_error
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:do_spurious_interrupt_bug
Cyclomatic Complexity 3 arch/x86/kernel/traps.c:do_device_not_available
Cyclomatic Complexity 1 arch/x86/kernel/traps.c:trap_init
--
In file included from arch/x86/kernel/dumpstack_64.c:14:0:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:user_mode
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack_64.c:in_irq_stack
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack_64.c:in_exception_stack
Cyclomatic Complexity 5 arch/x86/kernel/dumpstack_64.c:stack_type_name
Cyclomatic Complexity 11 arch/x86/kernel/dumpstack_64.c:get_stack_info
Cyclomatic Complexity 8 arch/x86/kernel/dumpstack_64.c:show_regs
--
In file included from arch/x86/kernel/dumpstack.c:16:0:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size_nocheck
Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
Cyclomatic Complexity 2 include/linux/printk.h:console_verbose
Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
Cyclomatic Complexity 1 arch/x86/include/asm/ptrace.h:kernel_stack_pointer
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_read
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_cmpxchg
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_save_flags
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_restore
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_disable
Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_save
Cyclomatic Complexity 1 arch/x86/include/asm/preempt.h:preempt_count
Cyclomatic Complexity 3 include/asm-generic/qspinlock.h:queued_spin_trylock
Cyclomatic Complexity 2 include/asm-generic/qspinlock.h:queued_spin_lock
Cyclomatic Complexity 1 include/linux/mm.h:debug_pagealloc_enabled
Cyclomatic Complexity 1 include/linux/module.h:print_modules
Cyclomatic Complexity 1 include/linux/ftrace.h:ftrace_graph_ret_addr
Cyclomatic Complexity 1 include/linux/sched/task_stack.h:task_stack_page
Cyclomatic Complexity 5 arch/x86/include/asm/stacktrace.h:on_stack
Cyclomatic Complexity 1 arch/x86/include/asm/unwind.h:unwind_done
Cyclomatic Complexity 3 arch/x86/include/asm/unwind.h:unwind_get_entry_regs
Cyclomatic Complexity 1 arch/x86/include/asm/cpu_entry_area.h:cpu_entry_stack
Cyclomatic Complexity 3 arch/x86/include/asm/stacktrace.h:get_stack_pointer
Cyclomatic Complexity 2 arch/x86/include/asm/unwind.h:unwind_start
Cyclomatic Complexity 1 include/linux/nmi.h:touch_nmi_watchdog
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:printk_stack_address
Cyclomatic Complexity 2 arch/x86/include/asm/qspinlock.h:native_queued_spin_unlock
Cyclomatic Complexity 1 arch/x86/include/asm/qspinlock.h:queued_spin_unlock
Cyclomatic Complexity 1 include/linux/kernel.h:kstrtoul
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:code_bytes_setup
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:in_task_stack
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:in_entry_stack
Cyclomatic Complexity 1 arch/x86/kernel/dumpstack.c:show_iret_regs
Cyclomatic Complexity 5 arch/x86/kernel/dumpstack.c:show_regs_if_on_stack
Cyclomatic Complexity 16 arch/x86/kernel/dumpstack.c:show_trace_log_lvl
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:show_stack
Cyclomatic Complexity 1 arch/x86/kernel/dumpstack.c:show_stack_regs
Cyclomatic Complexity 3 arch/x86/kernel/dumpstack.c:oops_begin
Cyclomatic Complexity 4 arch/x86/kernel/dumpstack.c:oops_end
Cyclomatic Complexity 3 arch/x86/kernel/dumpstack.c:__die
Cyclomatic Complexity 2 arch/x86/kernel/dumpstack.c:die
--
In file included from arch/x86/kernel/setup.c:45:0:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
Cyclomatic Complexity 1 arch/x86/include/asm/kaslr.h:kernel_randomize_memory
Cyclomatic Complexity 1 arch/x86/include/asm/page_types.h:get_max_mapped
Cyclomatic Complexity 1 include/linux/string.h:strnlen
Cyclomatic Complexity 4 include/linux/string.h:strlen
Cyclomatic Complexity 6 include/linux/string.h:strlcpy
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 1 arch/x86/include/asm/special_insns.h:native_read_cr4
Cyclomatic Complexity 1 arch/x86/include/asm/special_insns.h:__read_cr4
Cyclomatic Complexity 1 arch/x86/include/asm/mpspec.h:get_smp_config
Cyclomatic Complexity 1 arch/x86/include/asm/mpspec.h:find_smp_config
Cyclomatic Complexity 1 arch/x86/include/asm/numa.h:init_cpu_to_node
Cyclomatic Complexity 1 arch/x86/include/asm/apic.h:generic_apic_probe
Cyclomatic Complexity 1 arch/x86/include/asm/apic.h:check_x2apic
Cyclomatic Complexity 1 include/linux/kdev_t.h:old_decode_dev
Cyclomatic Complexity 1 include/linux/sfi.h:sfi_init
Cyclomatic Complexity 1 include/linux/efi.h:efi_esrt_init
Cyclomatic Complexity 1 include/linux/efi.h:efi_fake_memmap
Cyclomatic Complexity 1 include/linux/efi.h:efi_enabled
Cyclomatic Complexity 1 include/linux/iscsi_ibft.h:find_ibft_region
Cyclomatic Complexity 1 include/linux/dma-contiguous.h:dma_contiguous_reserve
Cyclomatic Complexity 1 include/linux/usb/xhci-dbgp.h:early_xdbc_setup_hardware
Cyclomatic Complexity 1 include/linux/usb/xhci-dbgp.h:early_xdbc_register_console
Cyclomatic Complexity 1 arch/x86/include/asm/mtrr.h:mtrr_trim_uncached_memory
Cyclomatic Complexity 1 arch/x86/include/asm/setup.h:kaslr_enabled
Cyclomatic Complexity 1 arch/x86/include/asm/setup.h:kaslr_offset
Cyclomatic Complexity 1 arch/x86/include/asm/efi.h:parse_efi_setup
Cyclomatic Complexity 1 arch/x86/include/asm/kasan.h:kasan_init
Cyclomatic Complexity 1 arch/x86/include/asm/gart.h:early_gart_iommu_check
Cyclomatic Complexity 1 arch/x86/include/asm/mpx.h:mpx_mm_init
Cyclomatic Complexity 1 arch/x86/include/asm/mmu_context.h:vma_pkey
Cyclomatic Complexity 1 arch/x86/include/asm/olpc_ofw.h:olpc_ofw_detect
Cyclomatic Complexity 1 arch/x86/include/asm/olpc_ofw.h:setup_olpc_ofw_pgd
Cyclomatic Complexity 1 arch/x86/include/asm/prom.h:add_dtb
Cyclomatic Complexity 1 arch/x86/include/asm/prom.h:x86_dtb_init
Cyclomatic Complexity 1 arch/x86/include/asm/unwind.h:unwind_init
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:copy_edd
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:get_ramdisk_image
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:get_ramdisk_size
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:parse_reservelow
Cyclomatic Complexity 3 arch/x86/kernel/setup.c:early_reserve_initrd
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_ibft_region
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_brk
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_low_memory_range
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:dump_kernel_offset
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:memblock_x86_reserve_range_setup_data
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:parse_setup_data
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:e820_add_kernel_range
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_bios_range
Cyclomatic Complexity 1 arch/x86/include/asm/mtrr.h:mtrr_bp_init
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:snb_gfx_workaround_needed
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:trim_snb_memory
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:trim_platform_memory_ranges
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:relocate_initrd
Cyclomatic Complexity 4 arch/x86/kernel/setup.c:reserve_initrd
Cyclomatic Complexity 5 arch/x86/kernel/setup.c:reserve_crashkernel_low
Cyclomatic Complexity 12 arch/x86/kernel/setup.c:reserve_crashkernel
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:register_kernel_offset_dumper
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:__brk_reservation_fn_dmi_alloc__
Cyclomatic Complexity 1 arch/x86/kernel/setup.c:extend_brk
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:reserve_standard_io_resources
Cyclomatic Complexity 14 arch/x86/kernel/setup.c:setup_arch
Cyclomatic Complexity 2 arch/x86/kernel/setup.c:arch_show_smap
--
In file included from include/linux/crash_dump.h:5:0,
from arch/x86/kernel/e820.c:11:
>> include/linux/kexec.h:293:52: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
^~~~~~~~~~~~~~
include/linux/kexec.h:297:48: warning: 'struct purgatory_info' declared inside parameter list will not be visible outside of this definition or declaration
int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
^~~~~~~~~~~~~~
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
Cyclomatic Complexity 1 include/linux/printk.h:early_printk
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 4 include/linux/string.h:memcpy
Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
Cyclomatic Complexity 68 include/linux/slab.h:kmalloc_large
Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
Cyclomatic Complexity 1 include/linux/suspend.h:register_nosave_region
Cyclomatic Complexity 1 include/linux/firmware-map.h:firmware_map_add_early
Cyclomatic Complexity 8 arch/x86/kernel/e820.c:__e820__mapped_all
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:cpcompare
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820_search_gap
Cyclomatic Complexity 8 arch/x86/kernel/e820.c:e820_type_to_string
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820_type_to_iomem_type
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820_type_to_iores_desc
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:do_mark_busy
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:ram_alignment
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:__e820__range_add
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820_print_type
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820_end_pfn
Cyclomatic Complexity 10 arch/x86/kernel/e820.c:__e820__range_update
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_update_kexec
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__register_nvs_regions
Cyclomatic Complexity 0 arch/x86/kernel/e820.c:early_panic
Cyclomatic Complexity 2 include/linux/memblock.h:memblock_dump_all
Cyclomatic Complexity 6 arch/x86/kernel/e820.c:e820__mapped_any
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__mapped_all
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__get_entry_type
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_add
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:__append_e820_table
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:append_e820_table
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__print_table
Cyclomatic Complexity 18 arch/x86/kernel/e820.c:e820__update_table
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__update_table_kexec
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__range_update
Cyclomatic Complexity 12 arch/x86/kernel/e820.c:e820__range_remove
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:parse_memopt
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__update_table_print
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__setup_pci_gap
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__reallocate_tables
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__memory_setup_extended
Cyclomatic Complexity 5 arch/x86/kernel/e820.c:e820__register_nosave_regions
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__memblock_alloc_reserved
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__end_of_ram_pfn
Cyclomatic Complexity 9 arch/x86/kernel/e820.c:parse_memmap_one
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:parse_memmap_opt
Cyclomatic Complexity 1 arch/x86/kernel/e820.c:e820__end_of_low_ram_pfn
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__reserve_setup_data
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__finish_early_params
Cyclomatic Complexity 4 arch/x86/kernel/e820.c:e820__reserve_resources
Cyclomatic Complexity 7 arch/x86/kernel/e820.c:e820__reserve_resources_late
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__memory_setup_default
Cyclomatic Complexity 2 arch/x86/kernel/e820.c:e820__memory_setup
Cyclomatic Complexity 3 arch/x86/kernel/e820.c:e820__memblock_setup
..

vim +293 include/linux/kexec.h

286
287 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
288 unsigned long buf_len);
289 void * __weak arch_kexec_kernel_image_load(struct kimage *image);
290 int __weak arch_kimage_file_post_load_cleanup(struct kimage *image);
291 int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
292 unsigned long buf_len);
> 293 int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
294 Elf_Shdr *section,
295 const Elf_Shdr *relsec,
296 const Elf_Shdr *symtab);
297 int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
298 Elf_Shdr *section,
299 const Elf_Shdr *relsec,
300 const Elf_Shdr *symtab);
301 void arch_kexec_protect_crashkres(void);
302 void arch_kexec_unprotect_crashkres(void);
303

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (24.95 kB)
.config.gz (23.62 kB)
Download all attachments

2018-02-28 16:42:54

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 10/11] kexec_file: Allow archs to set purgatory load address

Hi Philipp,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.16-rc3 next-20180228]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538
config: i386-randconfig-a0-201808 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All warnings (new ones prefixed by >>):

In file included from include/linux/crash_dump.h:5:0,
from drivers/scsi/aacraid/commsup.c:36:
>> include/linux/kexec.h:237:62: warning: 'struct kexec_buf' declared inside parameter list
extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
^
include/linux/kexec.h:237:62: warning: its scope is only this definition or declaration, which is probably not what you want
include/linux/kexec.h:291:10: warning: 'struct purgatory_info' declared inside parameter list
const Elf_Shdr *symtab);
^
include/linux/kexec.h:295:6: warning: 'struct purgatory_info' declared inside parameter list
const Elf_Shdr *symtab);
^

vim +237 include/linux/kexec.h

225
226 /* kexec interface functions */
227 extern void machine_kexec(struct kimage *image);
228 extern int machine_kexec_prepare(struct kimage *image);
229 extern void machine_kexec_cleanup(struct kimage *image);
230 extern asmlinkage long sys_kexec_load(unsigned long entry,
231 unsigned long nr_segments,
232 struct kexec_segment __user *segments,
233 unsigned long flags);
234 extern int kernel_kexec(void);
235 extern struct page *kimage_alloc_control_pages(struct kimage *image,
236 unsigned int order);
> 237 extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
238 extern int kexec_purgatory_get_set_symbol(struct kimage *image,
239 const char *name, void *buf,
240 unsigned int size, bool get_value);
241 extern void *kexec_purgatory_get_symbol_addr(struct kimage *image,
242 const char *name);
243 extern void __crash_kexec(struct pt_regs *);
244 extern void crash_kexec(struct pt_regs *);
245 int kexec_should_crash(struct task_struct *);
246 int kexec_crash_loaded(void);
247 void crash_save_cpu(struct pt_regs *regs, int cpu);
248 extern int kimage_crash_copy_vmcoreinfo(struct kimage *image);
249

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (2.83 kB)
.config.gz (29.08 kB)
Download all attachments

2018-02-28 22:51:24

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 07/11] kexec_file: Simplify kexec_purgatory_setup_sechdrs 1

Hi Philipp,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc3 next-20180228]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538
config: x86_64-randconfig-s4-03010216 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

Note: the linux-review/Philipp-Rudo/kexec_file-Clean-up-purgatory-load/20180228-223538 HEAD 28c77b126e4b2796074bd704e2370a38beb037c1 builds fine.
It only hurts bisectibility.

All errors (new ones prefixed by >>):

kernel/kexec_file.c: In function 'kexec_purgatory_setup_sechdrs':
>> kernel/kexec_file.c:798:3: error: expected ';' before '}' token
}
^

vim +798 kernel/kexec_file.c

713
714 /*
715 * kexec_purgatory_setup_sechdrs - prepares the pi->sechdrs buffer.
716 * @pi: Purgatory to be loaded.
717 * @kbuf: Buffer prepared to store purgatory.
718 *
719 * Allocates the memory needed for the buffer. Caller is responsible to free
720 * the memory after use.
721 *
722 * Return: 0 on success, negative errno on error.
723 */
724 static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
725 struct kexec_buf *kbuf)
726 {
727 unsigned long curr_load_addr;
728 unsigned long load_addr;
729 unsigned long bss_addr;
730 unsigned long offset;
731 unsigned char *buf_addr;
732 unsigned char *src;
733 Elf_Shdr *sechdrs;
734 int i;
735
736 sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
737 if (!sechdrs)
738 return -ENOMEM;
739 memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff,
740 pi->ehdr->e_shnum * sizeof(Elf_Shdr));
741 pi->sechdrs = sechdrs;
742
743 /*
744 * We seem to have multiple copies of sections. First copy is which
745 * is embedded in kernel in read only section. Some of these sections
746 * will be copied to a temporary buffer and relocated. And these
747 * sections will finally be copied to their final destination at
748 * segment load time.
749 *
750 * Use ->sh_offset to reflect section address in memory. It will
751 * point to original read only copy if section is not allocatable.
752 * Otherwise it will point to temporary copy which will be relocated.
753 *
754 * Use ->sh_addr to contain final address of the section where it
755 * will go during execution time.
756 */
757 for (i = 0; i < pi->ehdr->e_shnum; i++) {
758 if (sechdrs[i].sh_type == SHT_NOBITS)
759 continue;
760
761 sechdrs[i].sh_offset = (unsigned long)pi->ehdr +
762 sechdrs[i].sh_offset;
763 }
764
765 /* Load SHF_ALLOC sections */
766 buf_addr = kbuf->buffer;
767 load_addr = curr_load_addr = kbuf->mem;
768 bss_addr = load_addr + kbuf->bufsz;
769 kbuf->image->start = pi->ehdr->e_entry;
770
771 for (i = 0; i < pi->ehdr->e_shnum; i++) {
772 unsigned long align;
773
774 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
775 continue;
776
777 align = sechdrs[i].sh_addralign;
778
779 if (sechdrs[i].sh_type == SHT_NOBITS) {
780 bss_addr = ALIGN(bss_addr, align);
781 sechdrs[i].sh_addr = bss_addr;
782 bss_addr += sechdrs[i].sh_size;
783 continue;
784 }
785
786 curr_load_addr = ALIGN(curr_load_addr, align);
787 offset = curr_load_addr - load_addr;
788 /* We already modifed ->sh_offset to keep src addr */
789 src = (char *)sechdrs[i].sh_offset;
790 memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
791
792 if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
793 pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
794 pi->ehdr->e_entry < (sechdrs[i].sh_addr
795 + sechdrs[i].sh_size)) {
796 kbuf->image->start -= sechdrs[i].sh_addr;
797 kbuf->image->start += curr_load_addr
> 798 }
799
800 /* Store load address and source address of section */
801 sechdrs[i].sh_addr = curr_load_addr;
802
803 /*
804 * This section got copied to temporary buffer. Update
805 * ->sh_offset accordingly.
806 */
807 sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
808
809 /* Advance to the next address */
810 curr_load_addr += sechdrs[i].sh_size;
811 }
812
813 return 0;
814 }
815

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (4.83 kB)
.config.gz (30.12 kB)
Download all attachments

2018-03-09 03:15:55

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 09/11] kexec_file: Remove mis-use of sh_offset field

On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> 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 <[email protected]>
> ---
> arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
> kernel/kexec_file.c | 33 +++------------------------------
> 2 files changed, 9 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..25b44d1a664a 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -736,28 +736,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.

It would be good to keep above part comment somewhere..

> - *
> - * 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 +764,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 +979,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
>

Thanks
Dave

2018-03-09 03:19:32

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 08/11] kexec_file: Simplify kexec_purgatory_setup_sechdrs 2

Hi,

On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> 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.
>

It looks better to use some patch subject eg below:
"Remove unnecessary variables in kexec_purgatory_setup_sechdrs"

> Signed-off-by: Philipp Rudo <[email protected]>
> ---
> 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 bb31a3b627c2..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
>

Thanks
Dave

2018-03-09 04:45:08

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 11/11] kexec_file: Move purgatories sha256 to common code

On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> The code to verify the new kernels sha digest are applicable for all
> architectures. Move it to common code.
>
> Signed-off-by: Philipp Rudo <[email protected]>
> ---
> arch/x86/purgatory/Makefile | 3 +++
> arch/x86/purgatory/purgatory.c | 2 +-
> {arch/x86/purgatory => include/linux}/sha256.h | 10 +++++++++-
> {arch/x86/purgatory => lib}/sha256.c | 4 ++--
> 4 files changed, 15 insertions(+), 4 deletions(-)
> rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> 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/sha256.h b/include/linux/sha256.h
> similarity index 63%
> rename from arch/x86/purgatory/sha256.h
> rename to include/linux/sha256.h
> index 2867d9825a57..43a20ac33688 100644
> --- a/arch/x86/purgatory/sha256.h
> +++ b/include/linux/sha256.h
> @@ -13,9 +13,17 @@
> #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
> + */

should move to use preferred comment format:
/*
* Stand-alone ...
* ...
*/

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

Hmm, I'm not sure if moving to linux/string.h will have some side
effects..

>
> static inline u32 Ch(u32 x, u32 y, u32 z)
> {
> --
> 2.13.5
>

Thanks
Dave

2018-03-09 05:20:59

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Philipp,
On 02/26/18 at 04:16pm, Philipp Rudo wrote:
>
> 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: Simplify kexec_purgatory_setup_sechdrs 1
> kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> kexec_file: Remove mis-use of sh_offset field
> 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 +-
> include/linux/kexec.h | 38 +--
> {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> kernel/kexec_file.c | 375 ++++++++++++-------------
> {arch/x86/purgatory => lib}/sha256.c | 4 +-
> 9 files changed, 244 insertions(+), 271 deletions(-)
> rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> rename {arch/x86/purgatory => lib}/sha256.c (99%)
>
> --
> 2.13.5
>

I did a test on x86, but it failed:
[ 15.636489] kexec: Undefined symbol: memcpy
[ 15.636496] kexec-bzImage64: Loading purgatory failed
[ 33.603356] kexec: Undefined symbol: memcpy
[ 33.603362] kexec-bzImage64: Loading purgatory failed

I think this relates to the sha256 splitting patch.

After reverting the sha256 patch (the last one), rebuilt a kernel but it still
failed to load:

# kexec -d -s -l /home/dyoung/git/linux-x86/sign/bzImage.signed
Try gzip decompression.
Try LZMA decompression.
lzma_decompress_file: read on /home/dyoung/git/linux-x86/sign/bzImage.signed of 65536 bytes failed

Thanks
Dave

2018-03-09 05:35:49

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

On 03/09/18 at 01:19pm, Dave Young wrote:
> Hi Philipp,
> On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> >
> > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > kexec_file: Remove mis-use of sh_offset field
> > 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 +-
> > include/linux/kexec.h | 38 +--
> > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > kernel/kexec_file.c | 375 ++++++++++++-------------
> > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > 9 files changed, 244 insertions(+), 271 deletions(-)
> > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> >
> > --
> > 2.13.5
> >
>
> I did a test on x86, but it failed:
> [ 15.636489] kexec: Undefined symbol: memcpy
> [ 15.636496] kexec-bzImage64: Loading purgatory failed
> [ 33.603356] kexec: Undefined symbol: memcpy
> [ 33.603362] kexec-bzImage64: Loading purgatory failed
>
> I think this relates to the sha256 splitting patch.
>
> After reverting the sha256 patch (the last one), rebuilt a kernel but it still
> failed to load:
>
> # kexec -d -s -l /home/dyoung/git/linux-x86/sign/bzImage.signed
> Try gzip decompression.
> Try LZMA decompression.
> lzma_decompress_file: read on /home/dyoung/git/linux-x86/sign/bzImage.signed of 65536 bytes failed

Oops, this lzma error message should be not harmful, actually kernel should
have been loaded, I will do more tests anyway.

>
> Thanks
> Dave

2018-03-09 09:56:12

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 08/11] kexec_file: Simplify kexec_purgatory_setup_sechdrs 2

Hi Dave,

On Fri, 9 Mar 2018 11:18:05 +0800
Dave Young <[email protected]> wrote:

> Hi,
>
> On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > 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.
> >
>
> It looks better to use some patch subject eg below:
> "Remove unnecessary variables in kexec_purgatory_setup_sechdrs"

ok, done. I also renamed the patch before and after. The subjects now
are

kexec_file: Remove mis-use of sh_offset field during purgatory load
kexec_file: Remove unneeded variables in kexec_purgatory_setup_sechdrs
kexec_file: Remove unneeded for-loop in kexec_purgatory_setup_sechdrs

Thanks
Philipp


> > Signed-off-by: Philipp Rudo <[email protected]>
> > ---
> > 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 bb31a3b627c2..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
> >
>
> Thanks
> Dave
>


2018-03-09 10:03:59

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 09/11] kexec_file: Remove mis-use of sh_offset field

Hi Dave,


On Fri, 9 Mar 2018 11:14:20 +0800
Dave Young <[email protected]> wrote:

> On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > 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 <[email protected]>
> > ---
> > arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
> > kernel/kexec_file.c | 33 +++------------------------------
> > 2 files changed, 9 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..25b44d1a664a 100644
> > --- a/kernel/kexec_file.c
> > +++ b/kernel/kexec_file.c
> > @@ -736,28 +736,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.
>
> It would be good to keep above part comment somewhere..

there is a comment in include/linux/kexec.h for the purgatory_info->sechdrs
field saying

Temporary, modifiable buffer for sechdrs used for relocation.
This memory can be freed post image load

When you think this is not enough i can add a comment here like

The section headers in kexec_purgatory are read-only. In order to have them
modifiable make a temporary copy.

What do you think.

Thanks
Philipp

> > - *
> > - * 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 +764,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 +979,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
> >
>
> Thanks
> Dave
>


2018-03-09 10:13:23

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 11/11] kexec_file: Move purgatories sha256 to common code

Hi Dave,


On Fri, 9 Mar 2018 12:43:53 +0800
Dave Young <[email protected]> wrote:

> On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > The code to verify the new kernels sha digest are applicable for all
> > architectures. Move it to common code.
> >
> > Signed-off-by: Philipp Rudo <[email protected]>
> > ---
> > arch/x86/purgatory/Makefile | 3 +++
> > arch/x86/purgatory/purgatory.c | 2 +-
> > {arch/x86/purgatory => include/linux}/sha256.h | 10 +++++++++-
> > {arch/x86/purgatory => lib}/sha256.c | 4 ++--
> > 4 files changed, 15 insertions(+), 4 deletions(-)
> > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > 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/sha256.h b/include/linux/sha256.h
> > similarity index 63%
> > rename from arch/x86/purgatory/sha256.h
> > rename to include/linux/sha256.h
> > index 2867d9825a57..43a20ac33688 100644
> > --- a/arch/x86/purgatory/sha256.h
> > +++ b/include/linux/sha256.h
> > @@ -13,9 +13,17 @@
> > #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
> > + */
>
> should move to use preferred comment format:
> /*
> * Stand-alone ...
> * ...
> */

Fixed it.

> > +
> > 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"
>
> Hmm, I'm not sure if moving to linux/string.h will have some side
> effects..

Hmm, according to your other mail you are right. I'll have a closer look at it.

Thanks
Philipp

> >
> > static inline u32 Ch(u32 x, u32 y, u32 z)
> > {
> > --
> > 2.13.5
> >
>
> Thanks
> Dave
>


2018-03-09 10:15:59

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Dave,

On Fri, 9 Mar 2018 13:33:48 +0800
Dave Young <[email protected]> wrote:

> On 03/09/18 at 01:19pm, Dave Young wrote:
> > Hi Philipp,
> > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > >
> > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > kexec_file: Remove mis-use of sh_offset field
> > > 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 +-
> > > include/linux/kexec.h | 38 +--
> > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > >
> > > --
> > > 2.13.5
> > >
> >
> > I did a test on x86, but it failed:
> > [ 15.636489] kexec: Undefined symbol: memcpy
> > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > [ 33.603356] kexec: Undefined symbol: memcpy
> > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> >
> > I think this relates to the sha256 splitting patch.
> >
> > After reverting the sha256 patch (the last one), rebuilt a kernel but it still
> > failed to load:
> >
> > # kexec -d -s -l /home/dyoung/git/linux-x86/sign/bzImage.signed
> > Try gzip decompression.
> > Try LZMA decompression.
> > lzma_decompress_file: read on /home/dyoung/git/linux-x86/sign/bzImage.signed of 65536 bytes failed
>
> Oops, this lzma error message should be not harmful, actually kernel should
> have been loaded, I will do more tests anyway.

thanks for having a look. Please let me know when you find more problems.

Philipp

> >
> > Thanks
> > Dave
>


2018-03-09 14:27:37

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Dave,

On Fri, 9 Mar 2018 13:19:40 +0800
Dave Young <[email protected]> wrote:

> Hi Philipp,
> On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> >
> > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > kexec_file: Remove mis-use of sh_offset field
> > 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 +-
> > include/linux/kexec.h | 38 +--
> > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > kernel/kexec_file.c | 375 ++++++++++++-------------
> > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > 9 files changed, 244 insertions(+), 271 deletions(-)
> > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> >
> > --
> > 2.13.5
> >
>
> I did a test on x86, but it failed:
> [ 15.636489] kexec: Undefined symbol: memcpy
> [ 15.636496] kexec-bzImage64: Loading purgatory failed
> [ 33.603356] kexec: Undefined symbol: memcpy
> [ 33.603362] kexec-bzImage64: Loading purgatory failed
>
> I think this relates to the sha256 splitting patch.

I looked into this a little closer and i think i understood what happens.

There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
switching to linux/string.h there is no more definition for it. Leaving us with

$ readelf -s purgatory.ro
[...]
45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
[...]

To solve this problem I see two possibilities (example patches are at the end of
the mail):

1) Have arch dependent includes in lib/sha256.c
2) Add makefile magic so memcpy is defined

With both solutions the resulting purgatory.ro looks good. However both
solutions aren't perfect. For example in 2) i had too mix the linux/string.h
header with arch/x86/boot/string.c, because lib/string.c has too many
dependencies and does not compile in the purgatory. On the other hand having
arch dependent includes isn't that nice either ...

What's your opinion on this?

Thanks
Philipp

-----
Example solution 1

--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -17,9 +17,14 @@

#include <linux/bitops.h>
#include <linux/sha256.h>
-#include <linux/string.h>
#include <asm/byteorder.h>

+#ifdef CONFIG_X86
+#include "../arch/x86/boot/string.h"
+#else
+#include <linux/string.h>
+#endif /* CONFIG_X86 */
+
static inline u32 Ch(u32 x, u32 y, u32 z)
{
return z ^ (x & (y ^ z));

-----
Example solution 2

--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y

-purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
+purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
+ string.o memcpy_$(BITS).o memset_$(BITS).o

targets += $(purgatory-y)
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
@@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
$(obj)/sha256.o: $(srctree)/lib/sha256.c
$(call if_changed_rule,cc_o_c)

+$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
+ $(call if_changed_rule,cc_o_c)
+
+$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
+ $(call if_changed_rule,as_o_S)
+
+$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
+ $(call if_changed_rule,as_o_S)
+
LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
targets += purgatory.ro



2018-03-12 07:41:46

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Philipp,
On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> Hi Dave,
>
> On Fri, 9 Mar 2018 13:19:40 +0800
> Dave Young <[email protected]> wrote:
>
> > Hi Philipp,
> > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > >
> > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > kexec_file: Remove mis-use of sh_offset field
> > > 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 +-
> > > include/linux/kexec.h | 38 +--
> > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > >
> > > --
> > > 2.13.5
> > >
> >
> > I did a test on x86, but it failed:
> > [ 15.636489] kexec: Undefined symbol: memcpy
> > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > [ 33.603356] kexec: Undefined symbol: memcpy
> > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> >
> > I think this relates to the sha256 splitting patch.
>
> I looked into this a little closer and i think i understood what happens.
>
> There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> switching to linux/string.h there is no more definition for it. Leaving us with
>
> $ readelf -s purgatory.ro
> [...]
> 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> [...]
>
> To solve this problem I see two possibilities (example patches are at the end of
> the mail):
>
> 1) Have arch dependent includes in lib/sha256.c
> 2) Add makefile magic so memcpy is defined
>
> With both solutions the resulting purgatory.ro looks good. However both
> solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> header with arch/x86/boot/string.c, because lib/string.c has too many
> dependencies and does not compile in the purgatory. On the other hand having
> arch dependent includes isn't that nice either ...
>
> What's your opinion on this?

Looks like it is a mess, maybe the 1st one is better although it is also
ugly. Ccing Ingo see if he has some idea about this.

>
> Thanks
> Philipp
>
> -----
> Example solution 1
>
> --- a/lib/sha256.c
> +++ b/lib/sha256.c
> @@ -17,9 +17,14 @@
>
> #include <linux/bitops.h>
> #include <linux/sha256.h>
> -#include <linux/string.h>
> #include <asm/byteorder.h>
>
> +#ifdef CONFIG_X86
> +#include "../arch/x86/boot/string.h"
> +#else
> +#include <linux/string.h>
> +#endif /* CONFIG_X86 */
> +
> static inline u32 Ch(u32 x, u32 y, u32 z)
> {
> return z ^ (x & (y ^ z));
>
> -----
> Example solution 2
>
> --- a/arch/x86/purgatory/Makefile
> +++ b/arch/x86/purgatory/Makefile
> @@ -1,7 +1,8 @@
> # SPDX-License-Identifier: GPL-2.0
> OBJECT_FILES_NON_STANDARD := y
>
> -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> + string.o memcpy_$(BITS).o memset_$(BITS).o
>
> targets += $(purgatory-y)
> PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> $(obj)/sha256.o: $(srctree)/lib/sha256.c
> $(call if_changed_rule,cc_o_c)
>
> +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> + $(call if_changed_rule,cc_o_c)
> +
> +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> + $(call if_changed_rule,as_o_S)
> +
> +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> + $(call if_changed_rule,as_o_S)
> +
> LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> targets += purgatory.ro
>
>

Thanks
Dave

2018-03-12 07:43:38

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 09/11] kexec_file: Remove mis-use of sh_offset field

Hi Philipp,
On 03/09/18 at 11:02am, Philipp Rudo wrote:
> Hi Dave,
>
>
> On Fri, 9 Mar 2018 11:14:20 +0800
> Dave Young <[email protected]> wrote:
>
> > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > 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 <[email protected]>
> > > ---
> > > arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
> > > kernel/kexec_file.c | 33 +++------------------------------
> > > 2 files changed, 9 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..25b44d1a664a 100644
> > > --- a/kernel/kexec_file.c
> > > +++ b/kernel/kexec_file.c
> > > @@ -736,28 +736,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.
> >
> > It would be good to keep above part comment somewhere..
>
> there is a comment in include/linux/kexec.h for the purgatory_info->sechdrs
> field saying
>
> Temporary, modifiable buffer for sechdrs used for relocation.
> This memory can be freed post image load
>
> When you think this is not enough i can add a comment here like
>
> The section headers in kexec_purgatory are read-only. In order to have them
> modifiable make a temporary copy.

Looks better to add above comment here.

>
> What do you think.
>
> Thanks
> Philipp
>
> > > - *
> > > - * 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 +764,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 +979,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
> > >
> >
> > Thanks
> > Dave
> >
>

Thanks
Dave

2018-03-12 09:44:29

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 09/11] kexec_file: Remove mis-use of sh_offset field

On Mon, 12 Mar 2018 15:42:18 +0800
Dave Young <[email protected]> wrote:

> Hi Philipp,
> On 03/09/18 at 11:02am, Philipp Rudo wrote:
> > Hi Dave,
> >
> >
> > On Fri, 9 Mar 2018 11:14:20 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > > 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 <[email protected]>
> > > > ---
> > > > arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
> > > > kernel/kexec_file.c | 33 +++------------------------------
> > > > 2 files changed, 9 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..25b44d1a664a 100644
> > > > --- a/kernel/kexec_file.c
> > > > +++ b/kernel/kexec_file.c
> > > > @@ -736,28 +736,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.
> > >
> > > It would be good to keep above part comment somewhere..
> >
> > there is a comment in include/linux/kexec.h for the purgatory_info->sechdrs
> > field saying
> >
> > Temporary, modifiable buffer for sechdrs used for relocation.
> > This memory can be freed post image load
> >
> > When you think this is not enough i can add a comment here like
> >
> > The section headers in kexec_purgatory are read-only. In order to have them
> > modifiable make a temporary copy.
>
> Looks better to add above comment here.

Ok, it's added. I'll wait what Ingo says about the string.c issue befor
sending around v2.

Thanks
Philipp

> >
> > What do you think.
> >
> > Thanks
> > Philipp
> >
> > > > - *
> > > > - * 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 +764,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 +979,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
> > > >
> > >
> > > Thanks
> > > Dave
> > >
> >
>
> Thanks
> Dave
>


2018-03-14 09:53:20

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Ingo,

do you have an idea about this? This problem is currently holding me back to
send a v2 of the patch set.

Thanks
Philipp

On Mon, 12 Mar 2018 15:40:16 +0800
Dave Young <[email protected]> wrote:

> Hi Philipp,
> On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > Hi Dave,
> >
> > On Fri, 9 Mar 2018 13:19:40 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > Hi Philipp,
> > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > >
> > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > kexec_file: Remove mis-use of sh_offset field
> > > > 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 +-
> > > > include/linux/kexec.h | 38 +--
> > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > >
> > > > --
> > > > 2.13.5
> > > >
> > >
> > > I did a test on x86, but it failed:
> > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > >
> > > I think this relates to the sha256 splitting patch.
> >
> > I looked into this a little closer and i think i understood what happens.
> >
> > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > switching to linux/string.h there is no more definition for it. Leaving us with
> >
> > $ readelf -s purgatory.ro
> > [...]
> > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > [...]
> >
> > To solve this problem I see two possibilities (example patches are at the end of
> > the mail):
> >
> > 1) Have arch dependent includes in lib/sha256.c
> > 2) Add makefile magic so memcpy is defined
> >
> > With both solutions the resulting purgatory.ro looks good. However both
> > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > header with arch/x86/boot/string.c, because lib/string.c has too many
> > dependencies and does not compile in the purgatory. On the other hand having
> > arch dependent includes isn't that nice either ...
> >
> > What's your opinion on this?
>
> Looks like it is a mess, maybe the 1st one is better although it is also
> ugly. Ccing Ingo see if he has some idea about this.
>
> >
> > Thanks
> > Philipp
> >
> > -----
> > Example solution 1
> >
> > --- a/lib/sha256.c
> > +++ b/lib/sha256.c
> > @@ -17,9 +17,14 @@
> >
> > #include <linux/bitops.h>
> > #include <linux/sha256.h>
> > -#include <linux/string.h>
> > #include <asm/byteorder.h>
> >
> > +#ifdef CONFIG_X86
> > +#include "../arch/x86/boot/string.h"
> > +#else
> > +#include <linux/string.h>
> > +#endif /* CONFIG_X86 */
> > +
> > static inline u32 Ch(u32 x, u32 y, u32 z)
> > {
> > return z ^ (x & (y ^ z));
> >
> > -----
> > Example solution 2
> >
> > --- a/arch/x86/purgatory/Makefile
> > +++ b/arch/x86/purgatory/Makefile
> > @@ -1,7 +1,8 @@
> > # SPDX-License-Identifier: GPL-2.0
> > OBJECT_FILES_NON_STANDARD := y
> >
> > -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> > +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> > + string.o memcpy_$(BITS).o memset_$(BITS).o
> >
> > targets += $(purgatory-y)
> > PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > $(obj)/sha256.o: $(srctree)/lib/sha256.c
> > $(call if_changed_rule,cc_o_c)
> >
> > +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> > + $(call if_changed_rule,cc_o_c)
> > +
> > +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> > + $(call if_changed_rule,as_o_S)
> > +
> > +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> > + $(call if_changed_rule,as_o_S)
> > +
> > LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> > targets += purgatory.ro
> >
> >
>
> Thanks
> Dave
>


2018-03-15 07:35:43

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

On 03/12/18 at 03:40pm, Dave Young wrote:
> Hi Philipp,
> On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > Hi Dave,
> >
> > On Fri, 9 Mar 2018 13:19:40 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > Hi Philipp,
> > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > >
> > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > kexec_file: Remove mis-use of sh_offset field
> > > > 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 +-
> > > > include/linux/kexec.h | 38 +--
> > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > >
> > > > --
> > > > 2.13.5
> > > >
> > >
> > > I did a test on x86, but it failed:
> > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > >
> > > I think this relates to the sha256 splitting patch.
> >
> > I looked into this a little closer and i think i understood what happens.
> >
> > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > switching to linux/string.h there is no more definition for it. Leaving us with
> >
> > $ readelf -s purgatory.ro
> > [...]
> > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > [...]
> >
> > To solve this problem I see two possibilities (example patches are at the end of
> > the mail):
> >
> > 1) Have arch dependent includes in lib/sha256.c
> > 2) Add makefile magic so memcpy is defined
> >
> > With both solutions the resulting purgatory.ro looks good. However both
> > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > header with arch/x86/boot/string.c, because lib/string.c has too many
> > dependencies and does not compile in the purgatory. On the other hand having
> > arch dependent includes isn't that nice either ...
> >
> > What's your opinion on this?
>
> Looks like it is a mess, maybe the 1st one is better although it is also
> ugly. Ccing Ingo see if he has some idea about this.

Maybe something like below is better if no other idea:

diff --git a/arch/x86/boot/string_builtin.c b/arch/x86/boot/string_builtin.c
new file mode 100644
index 000000000000..9099f949fb41
--- /dev/null
+++ b/arch/x86/boot/string_builtin.c
@@ -0,0 +1,11 @@
+#include <linux/types.h>
+
+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/string.c b/arch/x86/purgatory/string.c
index d886b1fa36f0..e12c78fcd59f 100644
--- a/arch/x86/purgatory/string.c
+++ b/arch/x86/purgatory/string.c
@@ -11,3 +11,4 @@
*/

#include "../boot/string.c"
+#include "../boot/string_builtin.c"

>
> >
> > Thanks
> > Philipp
> >
> > -----
> > Example solution 1
> >
> > --- a/lib/sha256.c
> > +++ b/lib/sha256.c
> > @@ -17,9 +17,14 @@
> >
> > #include <linux/bitops.h>
> > #include <linux/sha256.h>
> > -#include <linux/string.h>
> > #include <asm/byteorder.h>
> >
> > +#ifdef CONFIG_X86
> > +#include "../arch/x86/boot/string.h"
> > +#else
> > +#include <linux/string.h>
> > +#endif /* CONFIG_X86 */
> > +
> > static inline u32 Ch(u32 x, u32 y, u32 z)
> > {
> > return z ^ (x & (y ^ z));
> >
> > -----
> > Example solution 2
> >
> > --- a/arch/x86/purgatory/Makefile
> > +++ b/arch/x86/purgatory/Makefile
> > @@ -1,7 +1,8 @@
> > # SPDX-License-Identifier: GPL-2.0
> > OBJECT_FILES_NON_STANDARD := y
> >
> > -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> > +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> > + string.o memcpy_$(BITS).o memset_$(BITS).o
> >
> > targets += $(purgatory-y)
> > PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > $(obj)/sha256.o: $(srctree)/lib/sha256.c
> > $(call if_changed_rule,cc_o_c)
> >
> > +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> > + $(call if_changed_rule,cc_o_c)
> > +
> > +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> > + $(call if_changed_rule,as_o_S)
> > +
> > +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> > + $(call if_changed_rule,as_o_S)
> > +
> > LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> > targets += purgatory.ro
> >
> >
>
> Thanks
> Dave

2018-03-15 10:15:01

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Dave,

On Thu, 15 Mar 2018 15:34:22 +0800
Dave Young <[email protected]> wrote:

> On 03/12/18 at 03:40pm, Dave Young wrote:
> > Hi Philipp,
> > On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > > Hi Dave,
> > >
> > > On Fri, 9 Mar 2018 13:19:40 +0800
> > > Dave Young <[email protected]> wrote:
> > >
> > > > Hi Philipp,
> > > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > > >
> > > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > 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 +-
> > > > > include/linux/kexec.h | 38 +--
> > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > >
> > > > > --
> > > > > 2.13.5
> > > > >
> > > >
> > > > I did a test on x86, but it failed:
> > > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > > >
> > > > I think this relates to the sha256 splitting patch.
> > >
> > > I looked into this a little closer and i think i understood what happens.
> > >
> > > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > > switching to linux/string.h there is no more definition for it. Leaving us with
> > >
> > > $ readelf -s purgatory.ro
> > > [...]
> > > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > > [...]
> > >
> > > To solve this problem I see two possibilities (example patches are at the end of
> > > the mail):
> > >
> > > 1) Have arch dependent includes in lib/sha256.c
> > > 2) Add makefile magic so memcpy is defined
> > >
> > > With both solutions the resulting purgatory.ro looks good. However both
> > > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > > header with arch/x86/boot/string.c, because lib/string.c has too many
> > > dependencies and does not compile in the purgatory. On the other hand having
> > > arch dependent includes isn't that nice either ...
> > >
> > > What's your opinion on this?
> >
> > Looks like it is a mess, maybe the 1st one is better although it is also
> > ugly. Ccing Ingo see if he has some idea about this.
>
> Maybe something like below is better if no other idea:
>
> diff --git a/arch/x86/boot/string_builtin.c b/arch/x86/boot/string_builtin.c
> new file mode 100644
> index 000000000000..9099f949fb41
> --- /dev/null
> +++ b/arch/x86/boot/string_builtin.c
> @@ -0,0 +1,11 @@
> +#include <linux/types.h>
> +
> +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/string.c b/arch/x86/purgatory/string.c
> index d886b1fa36f0..e12c78fcd59f 100644
> --- a/arch/x86/purgatory/string.c
> +++ b/arch/x86/purgatory/string.c
> @@ -11,3 +11,4 @@
> */
>
> #include "../boot/string.c"
> +#include "../boot/string_builtin.c"

Looks like a good idea to me. Just to be sure, with this suggestion
lib/sha256.c stays unchanged, i.e. it includes linux/string.h?

The only thing I don't really like is adding the extra boot/string.builtin.c
file. For my taste adding the two functions directly to purgatory/string.c would
be nicer. However in the end it's "not my problem".

Thanks
Philipp

> >
> > >
> > > Thanks
> > > Philipp
> > >
> > > -----
> > > Example solution 1
> > >
> > > --- a/lib/sha256.c
> > > +++ b/lib/sha256.c
> > > @@ -17,9 +17,14 @@
> > >
> > > #include <linux/bitops.h>
> > > #include <linux/sha256.h>
> > > -#include <linux/string.h>
> > > #include <asm/byteorder.h>
> > >
> > > +#ifdef CONFIG_X86
> > > +#include "../arch/x86/boot/string.h"
> > > +#else
> > > +#include <linux/string.h>
> > > +#endif /* CONFIG_X86 */
> > > +
> > > static inline u32 Ch(u32 x, u32 y, u32 z)
> > > {
> > > return z ^ (x & (y ^ z));
> > >
> > > -----
> > > Example solution 2
> > >
> > > --- a/arch/x86/purgatory/Makefile
> > > +++ b/arch/x86/purgatory/Makefile
> > > @@ -1,7 +1,8 @@
> > > # SPDX-License-Identifier: GPL-2.0
> > > OBJECT_FILES_NON_STANDARD := y
> > >
> > > -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> > > +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> > > + string.o memcpy_$(BITS).o memset_$(BITS).o
> > >
> > > targets += $(purgatory-y)
> > > PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > $(obj)/sha256.o: $(srctree)/lib/sha256.c
> > > $(call if_changed_rule,cc_o_c)
> > >
> > > +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> > > + $(call if_changed_rule,cc_o_c)
> > > +
> > > +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> > > + $(call if_changed_rule,as_o_S)
> > > +
> > > +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> > > + $(call if_changed_rule,as_o_S)
> > > +
> > > LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> > > targets += purgatory.ro
> > >
> > >
> >
> > Thanks
> > Dave
>


2018-03-16 06:42:22

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

On 03/15/18 at 11:13am, Philipp Rudo wrote:
> Hi Dave,
>
> On Thu, 15 Mar 2018 15:34:22 +0800
> Dave Young <[email protected]> wrote:
>
> > On 03/12/18 at 03:40pm, Dave Young wrote:
> > > Hi Philipp,
> > > On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > > > Hi Dave,
> > > >
> > > > On Fri, 9 Mar 2018 13:19:40 +0800
> > > > Dave Young <[email protected]> wrote:
> > > >
> > > > > Hi Philipp,
> > > > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > > > >
> > > > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > > 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 +-
> > > > > > include/linux/kexec.h | 38 +--
> > > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > > >
> > > > > > --
> > > > > > 2.13.5
> > > > > >
> > > > >
> > > > > I did a test on x86, but it failed:
> > > > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > > > >
> > > > > I think this relates to the sha256 splitting patch.
> > > >
> > > > I looked into this a little closer and i think i understood what happens.
> > > >
> > > > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > > > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > > > switching to linux/string.h there is no more definition for it. Leaving us with
> > > >
> > > > $ readelf -s purgatory.ro
> > > > [...]
> > > > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > > > [...]
> > > >
> > > > To solve this problem I see two possibilities (example patches are at the end of
> > > > the mail):
> > > >
> > > > 1) Have arch dependent includes in lib/sha256.c
> > > > 2) Add makefile magic so memcpy is defined
> > > >
> > > > With both solutions the resulting purgatory.ro looks good. However both
> > > > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > > > header with arch/x86/boot/string.c, because lib/string.c has too many
> > > > dependencies and does not compile in the purgatory. On the other hand having
> > > > arch dependent includes isn't that nice either ...
> > > >
> > > > What's your opinion on this?
> > >
> > > Looks like it is a mess, maybe the 1st one is better although it is also
> > > ugly. Ccing Ingo see if he has some idea about this.
> >
> > Maybe something like below is better if no other idea:
> >
> > diff --git a/arch/x86/boot/string_builtin.c b/arch/x86/boot/string_builtin.c
> > new file mode 100644
> > index 000000000000..9099f949fb41
> > --- /dev/null
> > +++ b/arch/x86/boot/string_builtin.c
> > @@ -0,0 +1,11 @@
> > +#include <linux/types.h>
> > +
> > +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/string.c b/arch/x86/purgatory/string.c
> > index d886b1fa36f0..e12c78fcd59f 100644
> > --- a/arch/x86/purgatory/string.c
> > +++ b/arch/x86/purgatory/string.c
> > @@ -11,3 +11,4 @@
> > */
> >
> > #include "../boot/string.c"
> > +#include "../boot/string_builtin.c"
>
> Looks like a good idea to me. Just to be sure, with this suggestion
> lib/sha256.c stays unchanged, i.e. it includes linux/string.h?

Yes, I assumed so, one thing is I noticed linux/string.h uses __kernel_size_t, but
the boot/string.h use _size_t.

>
> The only thing I don't really like is adding the extra boot/string.builtin.c
> file. For my taste adding the two functions directly to purgatory/string.c would
> be nicer. However in the end it's "not my problem".

string.c is also included in boot/compressed/string.c which defines its
own version of memcpy. And in the boot/compressed/string.c version it
calls warn() which is a special function for decompressor used only.
I'm not sure how to merge them with one string.c now.

>
> Thanks
> Philipp
>
> > >
> > > >
> > > > Thanks
> > > > Philipp
> > > >
> > > > -----
> > > > Example solution 1
> > > >
> > > > --- a/lib/sha256.c
> > > > +++ b/lib/sha256.c
> > > > @@ -17,9 +17,14 @@
> > > >
> > > > #include <linux/bitops.h>
> > > > #include <linux/sha256.h>
> > > > -#include <linux/string.h>
> > > > #include <asm/byteorder.h>
> > > >
> > > > +#ifdef CONFIG_X86
> > > > +#include "../arch/x86/boot/string.h"
> > > > +#else
> > > > +#include <linux/string.h>
> > > > +#endif /* CONFIG_X86 */
> > > > +
> > > > static inline u32 Ch(u32 x, u32 y, u32 z)
> > > > {
> > > > return z ^ (x & (y ^ z));
> > > >
> > > > -----
> > > > Example solution 2
> > > >
> > > > --- a/arch/x86/purgatory/Makefile
> > > > +++ b/arch/x86/purgatory/Makefile
> > > > @@ -1,7 +1,8 @@
> > > > # SPDX-License-Identifier: GPL-2.0
> > > > OBJECT_FILES_NON_STANDARD := y
> > > >
> > > > -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> > > > +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> > > > + string.o memcpy_$(BITS).o memset_$(BITS).o
> > > >
> > > > targets += $(purgatory-y)
> > > > PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > > @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > > $(obj)/sha256.o: $(srctree)/lib/sha256.c
> > > > $(call if_changed_rule,cc_o_c)
> > > >
> > > > +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> > > > + $(call if_changed_rule,cc_o_c)
> > > > +
> > > > +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> > > > + $(call if_changed_rule,as_o_S)
> > > > +
> > > > +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> > > > + $(call if_changed_rule,as_o_S)
> > > > +
> > > > LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> > > > targets += purgatory.ro
> > > >
> > > >
> > >
> > > Thanks
> > > Dave
> >
>

Thanks
Dave

2018-03-20 09:41:41

by Philipp Rudo

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Dave,

sorry for the late answer.


On Fri, 16 Mar 2018 14:41:02 +0800
Dave Young <[email protected]> wrote:

> On 03/15/18 at 11:13am, Philipp Rudo wrote:
> > Hi Dave,
> >
> > On Thu, 15 Mar 2018 15:34:22 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > On 03/12/18 at 03:40pm, Dave Young wrote:
> > > > Hi Philipp,
> > > > On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > > > > Hi Dave,
> > > > >
> > > > > On Fri, 9 Mar 2018 13:19:40 +0800
> > > > > Dave Young <[email protected]> wrote:
> > > > >
> > > > > > Hi Philipp,
> > > > > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > > > > >
> > > > > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > > > 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 +-
> > > > > > > include/linux/kexec.h | 38 +--
> > > > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > > > >
> > > > > > > --
> > > > > > > 2.13.5
> > > > > > >
> > > > > >
> > > > > > I did a test on x86, but it failed:
> > > > > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > > > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > > > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > > > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > > > > >
> > > > > > I think this relates to the sha256 splitting patch.
> > > > >
> > > > > I looked into this a little closer and i think i understood what happens.
> > > > >
> > > > > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > > > > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > > > > switching to linux/string.h there is no more definition for it. Leaving us with
> > > > >
> > > > > $ readelf -s purgatory.ro
> > > > > [...]
> > > > > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > > > > [...]
> > > > >
> > > > > To solve this problem I see two possibilities (example patches are at the end of
> > > > > the mail):
> > > > >
> > > > > 1) Have arch dependent includes in lib/sha256.c
> > > > > 2) Add makefile magic so memcpy is defined
> > > > >
> > > > > With both solutions the resulting purgatory.ro looks good. However both
> > > > > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > > > > header with arch/x86/boot/string.c, because lib/string.c has too many
> > > > > dependencies and does not compile in the purgatory. On the other hand having
> > > > > arch dependent includes isn't that nice either ...
> > > > >
> > > > > What's your opinion on this?
> > > >
> > > > Looks like it is a mess, maybe the 1st one is better although it is also
> > > > ugly. Ccing Ingo see if he has some idea about this.
> > >
> > > Maybe something like below is better if no other idea:
> > >
> > > diff --git a/arch/x86/boot/string_builtin.c b/arch/x86/boot/string_builtin.c
> > > new file mode 100644
> > > index 000000000000..9099f949fb41
> > > --- /dev/null
> > > +++ b/arch/x86/boot/string_builtin.c
> > > @@ -0,0 +1,11 @@
> > > +#include <linux/types.h>
> > > +
> > > +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/string.c b/arch/x86/purgatory/string.c
> > > index d886b1fa36f0..e12c78fcd59f 100644
> > > --- a/arch/x86/purgatory/string.c
> > > +++ b/arch/x86/purgatory/string.c
> > > @@ -11,3 +11,4 @@
> > > */
> > >
> > > #include "../boot/string.c"
> > > +#include "../boot/string_builtin.c"
> >
> > Looks like a good idea to me. Just to be sure, with this suggestion
> > lib/sha256.c stays unchanged, i.e. it includes linux/string.h?
>
> Yes, I assumed so, one thing is I noticed linux/string.h uses __kernel_size_t, but
> the boot/string.h use _size_t.

I don't think the __kernel_size_t vs. _size_t is a problem. When I make gcc's
intermediate file

$ make /arch/x86/purgatory/string.i

the type doesn't change with and without my patches. In both cases size_t is
defined as

size_t -> __kernel_size_t -> __kernel_ulong_t -> unsigned long

So (at least for now) we are safe.

> >
> > The only thing I don't really like is adding the extra boot/string.builtin.c
> > file. For my taste adding the two functions directly to purgatory/string.c would
> > be nicer. However in the end it's "not my problem".
>
> string.c is also included in boot/compressed/string.c which defines its
> own version of memcpy. And in the boot/compressed/string.c version it
> calls warn() which is a special function for decompressor used only.
> I'm not sure how to merge them with one string.c now.

That's why i suggested to put the two functions into _purgatory_/string.c. In
the end the file would read

---
$ cat arch/x86/purgatory/string.c
/*
* Simple string functions.
*
* Copyright (C) 2014 Red Hat Inc.
*
* Author:
* Vivek Goyal <[email protected]>
*
* This source code is licensed under the GNU General Public License,
* 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);
}
---

Of course it would be even nicer having them in boot/string.c. But as you
already mentioned that would require a larger cleanup and should be done by
somebody with more experience on x86.

Thanks
Philipp

> >
> > Thanks
> > Philipp
> >
> > > >
> > > > >
> > > > > Thanks
> > > > > Philipp
> > > > >
> > > > > -----
> > > > > Example solution 1
> > > > >
> > > > > --- a/lib/sha256.c
> > > > > +++ b/lib/sha256.c
> > > > > @@ -17,9 +17,14 @@
> > > > >
> > > > > #include <linux/bitops.h>
> > > > > #include <linux/sha256.h>
> > > > > -#include <linux/string.h>
> > > > > #include <asm/byteorder.h>
> > > > >
> > > > > +#ifdef CONFIG_X86
> > > > > +#include "../arch/x86/boot/string.h"
> > > > > +#else
> > > > > +#include <linux/string.h>
> > > > > +#endif /* CONFIG_X86 */
> > > > > +
> > > > > static inline u32 Ch(u32 x, u32 y, u32 z)
> > > > > {
> > > > > return z ^ (x & (y ^ z));
> > > > >
> > > > > -----
> > > > > Example solution 2
> > > > >
> > > > > --- a/arch/x86/purgatory/Makefile
> > > > > +++ b/arch/x86/purgatory/Makefile
> > > > > @@ -1,7 +1,8 @@
> > > > > # SPDX-License-Identifier: GPL-2.0
> > > > > OBJECT_FILES_NON_STANDARD := y
> > > > >
> > > > > -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
> > > > > +purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o \
> > > > > + string.o memcpy_$(BITS).o memset_$(BITS).o
> > > > >
> > > > > targets += $(purgatory-y)
> > > > > PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > > > @@ -9,6 +10,15 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
> > > > > $(obj)/sha256.o: $(srctree)/lib/sha256.c
> > > > > $(call if_changed_rule,cc_o_c)
> > > > >
> > > > > +$(obj)/string.o: $(srctree)/arch/x86/boot/string.c
> > > > > + $(call if_changed_rule,cc_o_c)
> > > > > +
> > > > > +$(obj)/memset_$(BITS).o: $(srctree)/arch/x86/lib/memset_$(BITS).S
> > > > > + $(call if_changed_rule,as_o_S)
> > > > > +
> > > > > +$(obj)/memcpy_$(BITS).o: $(srctree)/arch/x86/lib/memcpy_$(BITS).S
> > > > > + $(call if_changed_rule,as_o_S)
> > > > > +
> > > > > LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
> > > > > targets += purgatory.ro
> > > > >
> > > > >
> > > >
> > > > Thanks
> > > > Dave
> > >
> >
>
> Thanks
> Dave
>


2018-03-20 09:52:12

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH 00/11] kexec_file: Clean up purgatory load

Hi Philipp,
On 03/20/18 at 10:39am, Philipp Rudo wrote:
> Hi Dave,
>
> sorry for the late answer.
>
>
> On Fri, 16 Mar 2018 14:41:02 +0800
> Dave Young <[email protected]> wrote:
>
> > On 03/15/18 at 11:13am, Philipp Rudo wrote:
> > > Hi Dave,
> > >
> > > On Thu, 15 Mar 2018 15:34:22 +0800
> > > Dave Young <[email protected]> wrote:
> > >
> > > > On 03/12/18 at 03:40pm, Dave Young wrote:
> > > > > Hi Philipp,
> > > > > On 03/09/18 at 03:25pm, Philipp Rudo wrote:
> > > > > > Hi Dave,
> > > > > >
> > > > > > On Fri, 9 Mar 2018 13:19:40 +0800
> > > > > > Dave Young <[email protected]> wrote:
> > > > > >
> > > > > > > Hi Philipp,
> > > > > > > On 02/26/18 at 04:16pm, Philipp Rudo wrote:
> > > > > > > >
> > > > > > > > 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: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > > > > 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 +-
> > > > > > > > include/linux/kexec.h | 38 +--
> > > > > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > > > > 9 files changed, 244 insertions(+), 271 deletions(-)
> > > > > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > > > > >
> > > > > > > > --
> > > > > > > > 2.13.5
> > > > > > > >
> > > > > > >
> > > > > > > I did a test on x86, but it failed:
> > > > > > > [ 15.636489] kexec: Undefined symbol: memcpy
> > > > > > > [ 15.636496] kexec-bzImage64: Loading purgatory failed
> > > > > > > [ 33.603356] kexec: Undefined symbol: memcpy
> > > > > > > [ 33.603362] kexec-bzImage64: Loading purgatory failed
> > > > > > >
> > > > > > > I think this relates to the sha256 splitting patch.
> > > > > >
> > > > > > I looked into this a little closer and i think i understood what happens.
> > > > > >
> > > > > > There is no definition of memcpy in arch/x86/boot/string.c, instead it's defined
> > > > > > in arch/x86/boot/string.h as __buildin_memcpy (same for memset). Thus by
> > > > > > switching to linux/string.h there is no more definition for it. Leaving us with
> > > > > >
> > > > > > $ readelf -s purgatory.ro
> > > > > > [...]
> > > > > > 45: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
> > > > > > [...]
> > > > > >
> > > > > > To solve this problem I see two possibilities (example patches are at the end of
> > > > > > the mail):
> > > > > >
> > > > > > 1) Have arch dependent includes in lib/sha256.c
> > > > > > 2) Add makefile magic so memcpy is defined
> > > > > >
> > > > > > With both solutions the resulting purgatory.ro looks good. However both
> > > > > > solutions aren't perfect. For example in 2) i had too mix the linux/string.h
> > > > > > header with arch/x86/boot/string.c, because lib/string.c has too many
> > > > > > dependencies and does not compile in the purgatory. On the other hand having
> > > > > > arch dependent includes isn't that nice either ...
> > > > > >
> > > > > > What's your opinion on this?
> > > > >
> > > > > Looks like it is a mess, maybe the 1st one is better although it is also
> > > > > ugly. Ccing Ingo see if he has some idea about this.
> > > >
> > > > Maybe something like below is better if no other idea:
> > > >
> > > > diff --git a/arch/x86/boot/string_builtin.c b/arch/x86/boot/string_builtin.c
> > > > new file mode 100644
> > > > index 000000000000..9099f949fb41
> > > > --- /dev/null
> > > > +++ b/arch/x86/boot/string_builtin.c
> > > > @@ -0,0 +1,11 @@
> > > > +#include <linux/types.h>
> > > > +
> > > > +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/string.c b/arch/x86/purgatory/string.c
> > > > index d886b1fa36f0..e12c78fcd59f 100644
> > > > --- a/arch/x86/purgatory/string.c
> > > > +++ b/arch/x86/purgatory/string.c
> > > > @@ -11,3 +11,4 @@
> > > > */
> > > >
> > > > #include "../boot/string.c"
> > > > +#include "../boot/string_builtin.c"
> > >
> > > Looks like a good idea to me. Just to be sure, with this suggestion
> > > lib/sha256.c stays unchanged, i.e. it includes linux/string.h?
> >
> > Yes, I assumed so, one thing is I noticed linux/string.h uses __kernel_size_t, but
> > the boot/string.h use _size_t.
>
> I don't think the __kernel_size_t vs. _size_t is a problem. When I make gcc's
> intermediate file
>
> $ make /arch/x86/purgatory/string.i
>
> the type doesn't change with and without my patches. In both cases size_t is
> defined as
>
> size_t -> __kernel_size_t -> __kernel_ulong_t -> unsigned long
>
> So (at least for now) we are safe.
>
> > >
> > > The only thing I don't really like is adding the extra boot/string.builtin.c
> > > file. For my taste adding the two functions directly to purgatory/string.c would
> > > be nicer. However in the end it's "not my problem".
> >
> > string.c is also included in boot/compressed/string.c which defines its
> > own version of memcpy. And in the boot/compressed/string.c version it
> > calls warn() which is a special function for decompressor used only.
> > I'm not sure how to merge them with one string.c now.
>
> That's why i suggested to put the two functions into _purgatory_/string.c. In
> the end the file would read
>
> ---
> $ cat arch/x86/purgatory/string.c
> /*
> * Simple string functions.
> *
> * Copyright (C) 2014 Red Hat Inc.
> *
> * Author:
> * Vivek Goyal <[email protected]>
> *
> * This source code is licensed under the GNU General Public License,
> * 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);
> }
> ---
>
> Of course it would be even nicer having them in boot/string.c. But as you
> already mentioned that would require a larger cleanup and should be done by
> somebody with more experience on x86.

Ok, I got your points, your proposal looks good to me if no better choice.

Thanks
Dave