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 7/9] x86/purgatory: Use fully linked PIE ELF executable
Date: Wed, 24 Apr 2024 17:53:17 +0200 [thread overview]
Message-ID: <20240424155309.1719454-18-ardb+git@google.com> (raw)
In-Reply-To: <20240424155309.1719454-11-ardb+git@google.com>
From: Ard Biesheuvel <ardb@kernel.org>
Now that the generic support is in place, switch to a fully linked PIE
ELF executable for the purgatory, so that it can be loaded as a single,
fully relocated image. This allows a lot of ugly post-processing logic
to simply be dropped.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/include/asm/kexec.h | 7 --
arch/x86/kernel/machine_kexec_64.c | 127 --------------------
arch/x86/purgatory/Makefile | 14 +--
3 files changed, 5 insertions(+), 143 deletions(-)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index ee7b32565e5f..c7cacc2e9dfb 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -191,13 +191,6 @@ void arch_kexec_unprotect_crashkres(void);
#define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres
#ifdef CONFIG_KEXEC_FILE
-struct purgatory_info;
-int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
- Elf_Shdr *section,
- const Elf_Shdr *relsec,
- const Elf_Shdr *symtab);
-#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
-
int arch_kimage_file_post_load_cleanup(struct kimage *image);
#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
#endif
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index bc0a5348b4a6..ded924423e50 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -371,133 +371,6 @@ void machine_kexec(struct kimage *image)
/* arch-dependent functionality related to kexec file-based syscall */
#ifdef CONFIG_KEXEC_FILE
-/*
- * Apply purgatory relocations.
- *
- * @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(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;
- unsigned long address, sec_base, value;
- const char *strtab, *name, *shstrtab;
- const Elf_Shdr *sechdrs;
-
- /* 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;
-
- rel = (void *)pi->ehdr + relsec->sh_offset;
-
- pr_debug("Applying relocate section %s to %u\n",
- shstrtab + relsec->sh_name, relsec->sh_info);
-
- for (i = 0; i < relsec->sh_size / sizeof(*rel); i++) {
-
- /*
- * rel[i].r_offset contains byte offset from beginning
- * of section to the storage unit affected.
- *
- * 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 = 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;
-
- /*
- * rel[i].r_info contains information about symbol table index
- * w.r.t which relocation must be made and type of relocation
- * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
- * these respectively.
- */
- sym = (void *)pi->ehdr + symtabsec->sh_offset;
- sym += ELF64_R_SYM(rel[i].r_info);
-
- if (sym->st_name)
- name = strtab + sym->st_name;
- else
- name = shstrtab + sechdrs[sym->st_shndx].sh_name;
-
- pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n",
- name, sym->st_info, sym->st_shndx, sym->st_value,
- sym->st_size);
-
- if (sym->st_shndx == SHN_UNDEF) {
- pr_err("Undefined symbol: %s\n", name);
- return -ENOEXEC;
- }
-
- if (sym->st_shndx == SHN_COMMON) {
- pr_err("symbol '%s' in common section\n", name);
- return -ENOEXEC;
- }
-
- if (sym->st_shndx == SHN_ABS)
- sec_base = 0;
- 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 = pi->sechdrs[sym->st_shndx].sh_addr;
-
- value = sym->st_value;
- value += sec_base;
- value += rel[i].r_addend;
-
- switch (ELF64_R_TYPE(rel[i].r_info)) {
- case R_X86_64_NONE:
- break;
- case R_X86_64_64:
- *(u64 *)location = value;
- break;
- case R_X86_64_32:
- *(u32 *)location = value;
- if (value != *(u32 *)location)
- goto overflow;
- break;
- case R_X86_64_32S:
- *(s32 *)location = value;
- if ((s64)value != *(s32 *)location)
- goto overflow;
- break;
- case R_X86_64_PC32:
- case R_X86_64_PLT32:
- value -= (u64)address;
- *(u32 *)location = value;
- break;
- default:
- pr_err("Unknown rela relocation: %llu\n",
- ELF64_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-
-overflow:
- pr_err("Overflow in relocation type %d value 0x%lx\n",
- (int)ELF64_R_TYPE(rel[i].r_info), value);
- return -ENOEXEC;
-}
-
int arch_kimage_file_post_load_cleanup(struct kimage *image)
{
vfree(image->elf_headers);
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2df4a4b70ff5..acc09799af2a 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -26,12 +26,11 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
# Drop the function entry padding, which is not needed here
KBUILD_CFLAGS := $(filter-out $(PADDING_CFLAGS),$(KBUILD_CFLAGS))
-# When linking purgatory.ro with -r unresolved symbols are not checked,
-# also link a purgatory.chk binary without -r to check for unresolved symbols.
PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
-LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS)
-LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS)
-targets += purgatory.ro purgatory.chk
+PURGATORY_LDFLAGS += -T $(srctree)/include/asm-generic/purgatory.lds -pie
+PURGATORY_LDFLAGS += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
+LDFLAGS_purgatory.ro := $(PURGATORY_LDFLAGS)
+targets += purgatory.ro
# Sanitizer, etc. runtimes are unavailable and cannot be linked here.
GCOV_PROFILE := n
@@ -87,9 +86,6 @@ asflags-remove-y += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x))
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
$(call if_changed,ld)
-$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
- $(call if_changed,ld)
-
-$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro $(obj)/purgatory.chk
+$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro
obj-y += kexec-purgatory.o
--
2.44.0.769.g3c40516874-goog
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
WARNING: multiple messages have this Message-ID (diff)
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 7/9] x86/purgatory: Use fully linked PIE ELF executable
Date: Wed, 24 Apr 2024 17:53:17 +0200 [thread overview]
Message-ID: <20240424155309.1719454-18-ardb+git@google.com> (raw)
In-Reply-To: <20240424155309.1719454-11-ardb+git@google.com>
From: Ard Biesheuvel <ardb@kernel.org>
Now that the generic support is in place, switch to a fully linked PIE
ELF executable for the purgatory, so that it can be loaded as a single,
fully relocated image. This allows a lot of ugly post-processing logic
to simply be dropped.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/include/asm/kexec.h | 7 --
arch/x86/kernel/machine_kexec_64.c | 127 --------------------
arch/x86/purgatory/Makefile | 14 +--
3 files changed, 5 insertions(+), 143 deletions(-)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index ee7b32565e5f..c7cacc2e9dfb 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -191,13 +191,6 @@ void arch_kexec_unprotect_crashkres(void);
#define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres
#ifdef CONFIG_KEXEC_FILE
-struct purgatory_info;
-int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
- Elf_Shdr *section,
- const Elf_Shdr *relsec,
- const Elf_Shdr *symtab);
-#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
-
int arch_kimage_file_post_load_cleanup(struct kimage *image);
#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
#endif
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index bc0a5348b4a6..ded924423e50 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -371,133 +371,6 @@ void machine_kexec(struct kimage *image)
/* arch-dependent functionality related to kexec file-based syscall */
#ifdef CONFIG_KEXEC_FILE
-/*
- * Apply purgatory relocations.
- *
- * @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(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;
- unsigned long address, sec_base, value;
- const char *strtab, *name, *shstrtab;
- const Elf_Shdr *sechdrs;
-
- /* 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;
-
- rel = (void *)pi->ehdr + relsec->sh_offset;
-
- pr_debug("Applying relocate section %s to %u\n",
- shstrtab + relsec->sh_name, relsec->sh_info);
-
- for (i = 0; i < relsec->sh_size / sizeof(*rel); i++) {
-
- /*
- * rel[i].r_offset contains byte offset from beginning
- * of section to the storage unit affected.
- *
- * 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 = 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;
-
- /*
- * rel[i].r_info contains information about symbol table index
- * w.r.t which relocation must be made and type of relocation
- * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
- * these respectively.
- */
- sym = (void *)pi->ehdr + symtabsec->sh_offset;
- sym += ELF64_R_SYM(rel[i].r_info);
-
- if (sym->st_name)
- name = strtab + sym->st_name;
- else
- name = shstrtab + sechdrs[sym->st_shndx].sh_name;
-
- pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n",
- name, sym->st_info, sym->st_shndx, sym->st_value,
- sym->st_size);
-
- if (sym->st_shndx == SHN_UNDEF) {
- pr_err("Undefined symbol: %s\n", name);
- return -ENOEXEC;
- }
-
- if (sym->st_shndx == SHN_COMMON) {
- pr_err("symbol '%s' in common section\n", name);
- return -ENOEXEC;
- }
-
- if (sym->st_shndx == SHN_ABS)
- sec_base = 0;
- 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 = pi->sechdrs[sym->st_shndx].sh_addr;
-
- value = sym->st_value;
- value += sec_base;
- value += rel[i].r_addend;
-
- switch (ELF64_R_TYPE(rel[i].r_info)) {
- case R_X86_64_NONE:
- break;
- case R_X86_64_64:
- *(u64 *)location = value;
- break;
- case R_X86_64_32:
- *(u32 *)location = value;
- if (value != *(u32 *)location)
- goto overflow;
- break;
- case R_X86_64_32S:
- *(s32 *)location = value;
- if ((s64)value != *(s32 *)location)
- goto overflow;
- break;
- case R_X86_64_PC32:
- case R_X86_64_PLT32:
- value -= (u64)address;
- *(u32 *)location = value;
- break;
- default:
- pr_err("Unknown rela relocation: %llu\n",
- ELF64_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-
-overflow:
- pr_err("Overflow in relocation type %d value 0x%lx\n",
- (int)ELF64_R_TYPE(rel[i].r_info), value);
- return -ENOEXEC;
-}
-
int arch_kimage_file_post_load_cleanup(struct kimage *image)
{
vfree(image->elf_headers);
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2df4a4b70ff5..acc09799af2a 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -26,12 +26,11 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
# Drop the function entry padding, which is not needed here
KBUILD_CFLAGS := $(filter-out $(PADDING_CFLAGS),$(KBUILD_CFLAGS))
-# When linking purgatory.ro with -r unresolved symbols are not checked,
-# also link a purgatory.chk binary without -r to check for unresolved symbols.
PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
-LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS)
-LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS)
-targets += purgatory.ro purgatory.chk
+PURGATORY_LDFLAGS += -T $(srctree)/include/asm-generic/purgatory.lds -pie
+PURGATORY_LDFLAGS += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
+LDFLAGS_purgatory.ro := $(PURGATORY_LDFLAGS)
+targets += purgatory.ro
# Sanitizer, etc. runtimes are unavailable and cannot be linked here.
GCOV_PROFILE := n
@@ -87,9 +86,6 @@ asflags-remove-y += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x))
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
$(call if_changed,ld)
-$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
- $(call if_changed,ld)
-
-$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro $(obj)/purgatory.chk
+$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro
obj-y += kexec-purgatory.o
--
2.44.0.769.g3c40516874-goog
next prev parent reply other threads:[~2024-04-24 17:01 UTC|newest]
Thread overview: 38+ 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 ` 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 ` Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 2/9] x86/purgatory: Simplify stack handling Ard Biesheuvel
2024-04-24 15:53 ` Ard Biesheuvel
2024-04-24 18:26 ` Nathan Chancellor
2024-04-24 18:26 ` Nathan Chancellor
2024-04-26 21:32 ` Justin Stitt
2024-04-26 21:32 ` Justin Stitt
2024-04-26 21:53 ` Nathan Chancellor
2024-04-26 21:53 ` Nathan Chancellor
2024-04-26 22:01 ` Justin Stitt
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 ` Ard Biesheuvel
2024-04-24 15:53 ` [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT Ard Biesheuvel
2024-04-24 15:53 ` Ard Biesheuvel
2024-04-24 17:38 ` Brian Gerst
2024-04-24 17:38 ` Brian Gerst
2024-04-24 17:53 ` Ard Biesheuvel
2024-04-24 17:53 ` Ard Biesheuvel
2024-04-24 19:00 ` Brian Gerst
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 ` 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 ` Ard Biesheuvel
2024-04-24 15:53 ` Ard Biesheuvel [this message]
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
2024-04-24 15:53 ` [RFC PATCH 9/9] kexec: Drop support for partially linked purgatory executables Ard Biesheuvel
2024-04-24 15:53 ` Ard Biesheuvel
2024-04-24 20:04 ` [RFC PATCH 0/9] kexec x86 purgatory cleanup Eric W. Biederman
2024-04-24 20:04 ` Eric W. Biederman
2024-04-24 20:52 ` Ard Biesheuvel
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-18-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 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.