From: Baoquan He <bhe@redhat.com>
To: Li Chen <me@linux.beauty>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Mimi Zohar <zohar@linux.ibm.com>,
Tushar Sugandhi <tusharsu@linux.microsoft.com>,
Eric Biggers <ebiggers@kernel.org>,
Alexander Graf <graf@amazon.com>,
Steven Chen <chenste@linux.microsoft.com>,
Coiby Xu <coxu@redhat.com>,
Sourabh Jain <sourabhjain@linux.ibm.com>,
Philipp Rudo <prudo@redhat.com>,
Ricardo Ribalda <ribalda@chromium.org>,
"Steven Rostedt (Google)" <rostedt@goodmis.org>,
Ross Zwisler <zwisler@google.com>,
kexec@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] kexec: derive purgatory entry from symbol
Date: Wed, 28 Jan 2026 17:26:10 +0800 [thread overview]
Message-ID: <aXnWMmyUMdbrqAiu@MiWiFi-R3L-srv> (raw)
In-Reply-To: <20260128043511.316860-1-me@linux.beauty>
On 01/28/26 at 12:35pm, Li Chen wrote:
> kexec_load_purgatory() derives image->start by locating e_entry inside an
> SHF_EXECINSTR section. If the purgatory object contains multiple executable
> sections with overlapping sh_addr, the entrypoint check can match more than
> once and trigger a WARN.
>
> Derive the entry section from the purgatory_start symbol when present and
> compute image->start from its final placement. Keep the existing e_entry
> fallback for purgatories that do not expose the symbol.
>
> WARNING: kernel/kexec_file.c:1009 at kexec_load_purgatory+0x395/0x3c0, CPU#10: kexec/1784
> Call Trace:
> <TASK>
> bzImage64_load+0x133/0xa00
> __do_sys_kexec_file_load+0x2b3/0x5c0
> do_syscall_64+0x81/0x610
> entry_SYSCALL_64_after_hwframe+0x76/0x7e
>
> Fixes: 8652d44f466a ("kexec: support purgatories with .text.hot sections")
> Signed-off-by: Li Chen <me@linux.beauty>
LGTM,
Acked-by: Baoquan He <bhe@redhat.com>
By the way, a warning need be 'Fixes' tag and back ported to stable
kernel?
Thanks
Baoquan
> ---
> clangelog:
> v2: move the helper body above kexec_purgatory_setup_sechdrs() in v2 to avoid
> the forward declaration, as suggested by Baoquan.
>
> kernel/kexec_file.c | 131 +++++++++++++++++++++++++-------------------
> 1 file changed, 74 insertions(+), 57 deletions(-)
>
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 3f1d6c4e8ff2..e9550bfbd02e 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -880,6 +880,60 @@ static int kexec_calculate_store_digests(struct kimage *image)
> }
>
> #ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY
> +/*
> + * 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;
> + const Elf_Sym *syms;
> + const char *strtab;
> + int i, k;
> +
> + if (!pi->ehdr)
> + return NULL;
> +
> + ehdr = pi->ehdr;
> + sechdrs = (void *)ehdr + ehdr->e_shoff;
> +
> + for (i = 0; i < ehdr->e_shnum; i++) {
> + if (sechdrs[i].sh_type != SHT_SYMTAB)
> + continue;
> +
> + if (sechdrs[i].sh_link >= ehdr->e_shnum)
> + /* Invalid strtab section number */
> + continue;
> + 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++) {
> + if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL)
> + continue;
> +
> + if (strcmp(strtab + syms[k].st_name, name) != 0)
> + continue;
> +
> + if (syms[k].st_shndx == SHN_UNDEF ||
> + syms[k].st_shndx >= ehdr->e_shnum) {
> + pr_debug("Symbol: %s has bad section index %d.\n",
> + name, syms[k].st_shndx);
> + return NULL;
> + }
> +
> + /* Found the symbol we are looking for */
> + return &syms[k];
> + }
> + }
> +
> + return NULL;
> +}
> /*
> * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory.
> * @pi: Purgatory to be loaded.
> @@ -958,6 +1012,10 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
> unsigned long offset;
> size_t sechdrs_size;
> Elf_Shdr *sechdrs;
> + const Elf_Sym *entry_sym;
> + u16 entry_shndx = 0;
> + unsigned long entry_off = 0;
> + bool start_fixed = false;
> int i;
>
> /*
> @@ -975,6 +1033,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
> bss_addr = kbuf->mem + kbuf->bufsz;
> kbuf->image->start = pi->ehdr->e_entry;
>
> + entry_sym = kexec_purgatory_find_symbol(pi, "purgatory_start");
> + if (entry_sym) {
> + entry_shndx = entry_sym->st_shndx;
> + entry_off = entry_sym->st_value;
> + }
> +
> for (i = 0; i < pi->ehdr->e_shnum; i++) {
> unsigned long align;
> void *src, *dst;
> @@ -992,6 +1056,13 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
>
> offset = ALIGN(offset, align);
>
> + if (!start_fixed && entry_sym && i == entry_shndx &&
> + (sechdrs[i].sh_flags & SHF_EXECINSTR) &&
> + entry_off < sechdrs[i].sh_size) {
> + kbuf->image->start = kbuf->mem + offset + entry_off;
> + start_fixed = true;
> + }
> +
> /*
> * Check if the segment contains the entry point, if so,
> * calculate the value of image->start based on it.
> @@ -1002,13 +1073,14 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
> * 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 &&
> + if (!start_fixed && 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 == pi->ehdr->e_entry) {
> kbuf->image->start -= sechdrs[i].sh_addr;
> kbuf->image->start += kbuf->mem + offset;
> + start_fixed = true;
> }
>
> src = (void *)pi->ehdr + sechdrs[i].sh_offset;
> @@ -1126,61 +1198,6 @@ int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
> return ret;
> }
>
> -/*
> - * 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;
> - const Elf_Sym *syms;
> - const char *strtab;
> - int i, k;
> -
> - if (!pi->ehdr)
> - return NULL;
> -
> - ehdr = pi->ehdr;
> - sechdrs = (void *)ehdr + ehdr->e_shoff;
> -
> - for (i = 0; i < ehdr->e_shnum; i++) {
> - if (sechdrs[i].sh_type != SHT_SYMTAB)
> - continue;
> -
> - if (sechdrs[i].sh_link >= ehdr->e_shnum)
> - /* Invalid strtab section number */
> - continue;
> - 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++) {
> - if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL)
> - continue;
> -
> - if (strcmp(strtab + syms[k].st_name, name) != 0)
> - continue;
> -
> - if (syms[k].st_shndx == SHN_UNDEF ||
> - syms[k].st_shndx >= ehdr->e_shnum) {
> - pr_debug("Symbol: %s has bad section index %d.\n",
> - name, syms[k].st_shndx);
> - return NULL;
> - }
> -
> - /* Found the symbol we are looking for */
> - return &syms[k];
> - }
> - }
> -
> - return NULL;
> -}
> -
> void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
> {
> struct purgatory_info *pi = &image->purgatory_info;
> --
> 2.52.0
>
next prev parent reply other threads:[~2026-01-28 9:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-28 4:35 [PATCH v2] kexec: derive purgatory entry from symbol Li Chen
2026-01-28 9:26 ` Baoquan He [this message]
2026-01-28 19:19 ` Andrew Morton
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=aXnWMmyUMdbrqAiu@MiWiFi-R3L-srv \
--to=bhe@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=chenste@linux.microsoft.com \
--cc=coxu@redhat.com \
--cc=ebiggers@kernel.org \
--cc=graf@amazon.com \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=me@linux.beauty \
--cc=prudo@redhat.com \
--cc=ribalda@chromium.org \
--cc=rostedt@goodmis.org \
--cc=sourabhjain@linux.ibm.com \
--cc=tusharsu@linux.microsoft.com \
--cc=zohar@linux.ibm.com \
--cc=zwisler@google.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.