From: Ard Biesheuvel <ardb+git@google.com>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Ard Biesheuvel <ardb@kernel.org>,
Arnd Bergmann <arnd@arndb.de>,
Eric Biederman <ebiederm@xmission.com>,
kexec@lists.infradead.org, Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <ndesaulniers@google.com>,
Kees Cook <keescook@chromium.org>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
Masahiro Yamada <masahiroy@kernel.org>
Subject: [RFC PATCH 9/9] kexec: Drop support for partially linked purgatory executables
Date: Wed, 24 Apr 2024 17:53:19 +0200 [thread overview]
Message-ID: <20240424155309.1719454-20-ardb+git@google.com> (raw)
In-Reply-To: <20240424155309.1719454-11-ardb+git@google.com>
From: Ard Biesheuvel <ardb@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 <ardb@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
next prev parent reply other threads:[~2024-04-24 15:53 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-24 15:53 [RFC PATCH 0/9] kexec x86 purgatory cleanup Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 1/9] x86/purgatory: Drop function entry padding from purgatory Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 2/9] x86/purgatory: Simplify stack handling Ard Biesheuvel
2024-04-24 18:26 ` Nathan Chancellor
2024-04-26 21:32 ` Justin Stitt
2024-04-26 21:53 ` Nathan Chancellor
2024-04-26 22:01 ` Justin Stitt
2024-04-24 15:53 ` [RFC PATCH 3/9] x86/purgatory: Drop pointless GDT switch Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT Ard Biesheuvel
2024-04-24 17:38 ` Brian Gerst
2024-04-24 17:53 ` Ard Biesheuvel
2024-04-24 19:00 ` Brian Gerst
2024-04-24 15:53 ` [RFC PATCH 5/9] x86/purgatory: Simplify GDT and drop data segment Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 6/9] kexec: Add support for fully linked purgatory executables Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 7/9] x86/purgatory: Use fully linked PIE ELF executable Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 8/9] x86/purgatory: Simplify references to regs array Ard Biesheuvel
2024-04-24 15:53 ` Ard Biesheuvel [this message]
2024-04-24 20:04 ` [RFC PATCH 0/9] kexec x86 purgatory cleanup Eric W. Biederman
2024-04-24 20:52 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240424155309.1719454-20-ardb+git@google.com \
--to=ardb+git@google.com \
--cc=ardb@kernel.org \
--cc=arnd@arndb.de \
--cc=ebiederm@xmission.com \
--cc=justinstitt@google.com \
--cc=keescook@chromium.org \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox