From: Ard Biesheuvel <a...@kernel.org>

Remove the handling of purgatories that are allocated, loaded and
relocated as individual ELF sections, which requires a lot of
post-processing on the part of the kexec loader. This has been
superseded by the use of fully linked PIE executables, which do not
require such post-processing.

Signed-off-by: Ard Biesheuvel <a...@kernel.org>
---
 kernel/kexec_file.c | 271 +-------------------
 1 file changed, 14 insertions(+), 257 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 6379f8dfc29f..782a1247558c 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -808,228 +808,31 @@ static int kexec_calculate_store_digests(struct kimage 
*image)
 
 #ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY
 /*
- * 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)
-{
-       const Elf_Shdr *sechdrs;
-       unsigned long bss_align;
-       unsigned long bss_sz;
-       unsigned long align;
-       int i, ret;
-
-       sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
-       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))
-                       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;
-
-       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 bss_addr;
-       unsigned long offset;
-       size_t sechdrs_size;
-       Elf_Shdr *sechdrs;
-       int i;
-
-       /*
-        * The section headers in kexec_purgatory are read-only. In order to
-        * have them modifiable make a temporary copy.
-        */
-       sechdrs_size = array_size(sizeof(Elf_Shdr), pi->ehdr->e_shnum);
-       sechdrs = vzalloc(sechdrs_size);
-       if (!sechdrs)
-               return -ENOMEM;
-       memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff, sechdrs_size);
-       pi->sechdrs = sechdrs;
-
-       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;
-                       bss_addr += sechdrs[i].sh_size;
-                       continue;
-               }
-
-               offset = ALIGN(offset, align);
-
-               /*
-                * Check if the segment contains the entry point, if so,
-                * calculate the value of image->start based on it.
-                * If the compiler has produced more than one .text section
-                * (Eg: .text.hot), they are generally after the main .text
-                * section, and they shall not be used to calculate
-                * image->start. So do not re-calculate image->start if it
-                * is not set to the initial value, and warn the user so they
-                * have a chance to fix their purgatory's linker script.
-                */
-               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) &&
-                   !WARN_ON(kbuf->image->start != pi->ehdr->e_entry)) {
-                       kbuf->image->start -= sechdrs[i].sh_addr;
-                       kbuf->image->start += kbuf->mem + 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;
-               sechdrs[i].sh_offset = offset;
-               offset += sechdrs[i].sh_size;
-       }
-
-       return 0;
-}
-
-static int kexec_apply_relocations(struct kimage *image)
-{
-       int i, ret;
-       struct purgatory_info *pi = &image->purgatory_info;
-       const Elf_Shdr *sechdrs;
-
-       sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
-
-       for (i = 0; i < pi->ehdr->e_shnum; i++) {
-               const Elf_Shdr *relsec;
-               const Elf_Shdr *symtab;
-               Elf_Shdr *section;
-
-               relsec = sechdrs + i;
-
-               if (relsec->sh_type != SHT_RELA &&
-                   relsec->sh_type != SHT_REL)
-                       continue;
-
-               /*
-                * For section of type SHT_RELA/SHT_REL,
-                * ->sh_link contains section header index of associated
-                * symbol table. And ->sh_info contains section header
-                * index of section to which relocations apply.
-                */
-               if (relsec->sh_info >= pi->ehdr->e_shnum ||
-                   relsec->sh_link >= pi->ehdr->e_shnum)
-                       return -ENOEXEC;
-
-               section = pi->sechdrs + relsec->sh_info;
-               symtab = sechdrs + relsec->sh_link;
-
-               if (!(section->sh_flags & SHF_ALLOC))
-                       continue;
-
-               /*
-                * symtab->sh_link contain section header index of associated
-                * string table.
-                */
-               if (symtab->sh_link >= pi->ehdr->e_shnum)
-                       /* Invalid section number? */
-                       continue;
-
-               /*
-                * Respective architecture needs to provide support for applying
-                * relocations of type SHT_RELA/SHT_REL.
-                */
-               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;
-       }
-
-       return 0;
-}
-
-/*
- * kexec_load_purgatory_pie - Load the position independent purgatory object.
- * @pi:                Purgatory info struct.
+ * kexec_load_purgatory - Load and relocate the purgatory object.
+ * @image:     Image to add the purgatory to.
  * @kbuf:      Memory parameters to use.
  *
- * Load a purgatory PIE executable. This is a fully linked executable
- * consisting of a single PT_LOAD segment that does not require any relocation
- * processing.
+ * 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.
  */
-static int kexec_load_purgatory_pie(struct purgatory_info *pi,
-                                   struct kexec_buf *kbuf)
+int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
 {
-       const Elf_Phdr *phdr = (void *)pi->ehdr + pi->ehdr->e_phoff;
+       struct purgatory_info *pi = &image->purgatory_info;
+       const Elf_Phdr *phdr;
        int ret;
 
+       if (kexec_purgatory_size <= 0)
+               return -EINVAL;
+
+       pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
        if (pi->ehdr->e_phnum != 1)
                return -EINVAL;
 
+       phdr = (void *)pi->ehdr + pi->ehdr->e_phoff;
+
        kbuf->bufsz = phdr->p_filesz;
        kbuf->memsz = phdr->p_memsz;
        kbuf->buf_align = phdr->p_align;
@@ -1066,52 +869,6 @@ static int kexec_load_purgatory_pie(struct purgatory_info 
*pi,
        return ret;
 }
 
-/*
- * 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;
-
-       if (kexec_purgatory_size <= 0)
-               return -EINVAL;
-
-       pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
-
-       if (pi->ehdr->e_type != ET_REL)
-               return kexec_load_purgatory_pie(pi, kbuf);
-
-       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;
-
-       return 0;
-out:
-       vfree(pi->sechdrs);
-       pi->sechdrs = NULL;
-out_free_kbuf:
-       vfree(pi->purgatory_buf);
-       pi->purgatory_buf = NULL;
-       return ret;
-}
-
 /*
  * kexec_purgatory_find_symbol - find a symbol in the purgatory
  * @pi:                Purgatory to search in.
-- 
2.44.0.769.g3c40516874-goog


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to