From nobody Sun Feb 8 02:55:54 2026 Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78F0E30AABE for ; Wed, 28 Jan 2026 04:35:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.112 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769574946; cv=pass; b=Uf3N6ZGt0ZmuHJLuPbSrDr7T+qBjb5dkq1tCvhATXZU+9qCa7E++FT6XEbgU2OroGW1M/YGO+sWVpFCV1PSqwSlkY97+qtLpr8MdS/oXjPny3DEpaVXSaBMEbUjSl2peuVCBAd9q2GExgbMeDaINciLPA2/6v37n0f8gRTvg8ug= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769574946; c=relaxed/simple; bh=6ATvHsdYiip+kLXMIvbkWomgj0QqxXEs9g5FWAELr44=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=l93pijYtJjyvUWY3J/jFeuJrpUjXKL8m5A2lxhLJkgaGm6k9u5UQNwhtTaeiqp72wDz1kiQVtRI2Tuha+utSi1/MQU7WtkC1uFIX7OyEb4eEAIxSj4a9xndSTCNHKUJlhik5ccvWp3EU+/0SCFSoozmcPdYHVHqSpsm3SjFdSyQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.beauty; spf=pass smtp.mailfrom=linux.beauty; dkim=pass (1024-bit key) header.d=linux.beauty header.i=me@linux.beauty header.b=YE9RXlMa; arc=pass smtp.client-ip=136.143.188.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.beauty Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.beauty Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.beauty header.i=me@linux.beauty header.b="YE9RXlMa" ARC-Seal: i=1; a=rsa-sha256; t=1769574924; cv=none; d=zohomail.com; s=zohoarc; b=ljBIPtDTlVj/zVt0UVP9FiWrmE9LtNw1LIMNYSThgfcWVsdD604r35u3dhMuN/DDCmdR/4mSnTAgC27p4cVNrBz6LbDsjgBqwvBYYesJL39FuiV5zOxM8VlcswU7HHIsH02ftcMxNwTsHntSmOmE07A1MCHMnzcZrKTlC6PkYWo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769574924; h=Content-Transfer-Encoding:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=RJLog9pwWlh0Lb/QETgZDkyv5EZvOUryY5iGkIHTsDA=; b=hP6LEgymSEZWYGf7IGvPfHe+DTkPew5F8e+bQaF3IAKXVslJGVX+2XAxtp1yjsU6wtZKeQMQygiwN6RGMCGiuReIjhMfQCQTsP8/CY7z9BDqNNMeJLzo0p956LtY6/6GJoRk33zDPmcYgdAiCJue8nfFQsbvvqQ2QRuMrfn/4uE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=linux.beauty; spf=pass smtp.mailfrom=me@linux.beauty; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1769574923; s=zmail; d=linux.beauty; i=me@linux.beauty; h=From:From:To:To:Subject:Subject:Date:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To:Cc; bh=RJLog9pwWlh0Lb/QETgZDkyv5EZvOUryY5iGkIHTsDA=; b=YE9RXlMalpXdQPqyiV0lG1GedhE2AFn7Bl3nXlrJ8Sc6RnP8CRFUqHZtR3FLuFOq pr03NVKuaFh22cj8GXIwsfyGpYgTmRH+MPk09aCjiylCfipY2V8D5IrtrXtcLt8YVAb 0FgmPv4sssdIpLiwXLmP2BaDDVPoD5tfbgaAhals= Received: by mx.zohomail.com with SMTPS id 1769574921334574.8281592616415; Tue, 27 Jan 2026 20:35:21 -0800 (PST) From: Li Chen To: Andrew Morton , Baoquan He , Mimi Zohar , Tushar Sugandhi , Eric Biggers , Alexander Graf , Steven Chen , Coiby Xu , Li Chen , Sourabh Jain , Philipp Rudo , Ricardo Ribalda , "Steven Rostedt (Google)" , Ross Zwisler , kexec@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] kexec: derive purgatory entry from symbol Date: Wed, 28 Jan 2026 12:35:10 +0800 Message-ID: <20260128043511.316860-1-me@linux.beauty> X-Mailer: git-send-email 2.52.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" 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: 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 Acked-by: Baoquan He --- clangelog: v2: move the helper body above kexec_purgatory_setup_sechdrs() in v2 to avo= id 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) } =20 #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 *p= i, + 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 =3D pi->ehdr; + sechdrs =3D (void *)ehdr + ehdr->e_shoff; + + for (i =3D 0; i < ehdr->e_shnum; i++) { + if (sechdrs[i].sh_type !=3D SHT_SYMTAB) + continue; + + if (sechdrs[i].sh_link >=3D ehdr->e_shnum) + /* Invalid strtab section number */ + continue; + strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; + syms =3D (void *)ehdr + sechdrs[i].sh_offset; + + /* Go through symbols for a match */ + for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { + if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) + continue; + + if (strcmp(strtab + syms[k].st_name, name) !=3D 0) + continue; + + if (syms[k].st_shndx =3D=3D SHN_UNDEF || + syms[k].st_shndx >=3D 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 purga= tory_info *pi, unsigned long offset; size_t sechdrs_size; Elf_Shdr *sechdrs; + const Elf_Sym *entry_sym; + u16 entry_shndx =3D 0; + unsigned long entry_off =3D 0; + bool start_fixed =3D false; int i; =20 /* @@ -975,6 +1033,12 @@ static int kexec_purgatory_setup_sechdrs(struct purga= tory_info *pi, bss_addr =3D kbuf->mem + kbuf->bufsz; kbuf->image->start =3D pi->ehdr->e_entry; =20 + entry_sym =3D kexec_purgatory_find_symbol(pi, "purgatory_start"); + if (entry_sym) { + entry_shndx =3D entry_sym->st_shndx; + entry_off =3D entry_sym->st_value; + } + for (i =3D 0; i < pi->ehdr->e_shnum; i++) { unsigned long align; void *src, *dst; @@ -992,6 +1056,13 @@ static int kexec_purgatory_setup_sechdrs(struct purga= tory_info *pi, =20 offset =3D ALIGN(offset, align); =20 + if (!start_fixed && entry_sym && i =3D=3D entry_shndx && + (sechdrs[i].sh_flags & SHF_EXECINSTR) && + entry_off < sechdrs[i].sh_size) { + kbuf->image->start =3D kbuf->mem + offset + entry_off; + start_fixed =3D 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 pur= gatory_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 >=3D sechdrs[i].sh_addr && pi->ehdr->e_entry < (sechdrs[i].sh_addr + sechdrs[i].sh_size) && - !WARN_ON(kbuf->image->start !=3D pi->ehdr->e_entry)) { + kbuf->image->start =3D=3D pi->ehdr->e_entry) { kbuf->image->start -=3D sechdrs[i].sh_addr; kbuf->image->start +=3D kbuf->mem + offset; + start_fixed =3D true; } =20 src =3D (void *)pi->ehdr + sechdrs[i].sh_offset; @@ -1126,61 +1198,6 @@ int kexec_load_purgatory(struct kimage *image, struc= t kexec_buf *kbuf) return ret; } =20 -/* - * 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 *p= i, - 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 =3D pi->ehdr; - sechdrs =3D (void *)ehdr + ehdr->e_shoff; - - for (i =3D 0; i < ehdr->e_shnum; i++) { - if (sechdrs[i].sh_type !=3D SHT_SYMTAB) - continue; - - if (sechdrs[i].sh_link >=3D ehdr->e_shnum) - /* Invalid strtab section number */ - continue; - strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; - syms =3D (void *)ehdr + sechdrs[i].sh_offset; - - /* Go through symbols for a match */ - for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { - if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) - continue; - - if (strcmp(strtab + syms[k].st_name, name) !=3D 0) - continue; - - if (syms[k].st_shndx =3D=3D SHN_UNDEF || - syms[k].st_shndx >=3D 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 *na= me) { struct purgatory_info *pi =3D &image->purgatory_info; --=20 2.52.0