All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Ard Biesheuvel <ardb@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Kees Cook <kees@kernel.org>, Uros Bizjak <ubizjak@gmail.com>,
	Brian Gerst <brgerst@gmail.com>,
	linux-hardening@vger.kernel.org
Subject: [RFC/RFT PATCH 18/19] x86/boot: Implement support for RELA/RELR/REL runtime relocations
Date: Thu,  8 Jan 2026 09:25:45 +0000	[thread overview]
Message-ID: <20260108092526.28586-39-ardb@kernel.org> (raw)
In-Reply-To: <20260108092526.28586-21-ardb@kernel.org>

Given that the decompressor already incorporates an ELF loader that
parses the program headers of the decompressed ELF image, support for
dealing with the PT_DYNAMIC program header can be added quite easily,
which describes the location of the RELA and RELR relocation tables in
the image.

This is a more efficient, and more idiomatic format, which allows the
handling of boot-time randomization (KASLR) in a generic manner, rather
than based on a bespoke x86-specific relocation format. This is a
prerequisite for enabling further hardening measures that are
implemented in the ELF domain, i.e., fgkaslr.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/misc.c | 73 +++++++++++++++++++-
 include/uapi/linux/elf.h        |  3 +
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 1ea419cf88fe..bc5677e697ca 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -278,7 +278,68 @@ static inline void handle_relocations(void *output, unsigned long output_len,
 { }
 #endif
 
-static size_t parse_elf(void *output)
+#define ELF(type) __PASTE(__PASTE(Elf, __LONG_WIDTH__), __PASTE(_, type))
+
+static void handle_dynamic(const ELF(Dyn) *dyn, unsigned long p2v_offset,
+			   unsigned long va_shift)
+{
+	const ELF(Rela) *rela = NULL;
+	const ELF(Rel) *rel = NULL;
+	unsigned long *relr = NULL;
+	unsigned long *place;
+	int relasize = 0;
+	int relrsize = 0;
+	int relsize = 0;
+
+	for (auto d = dyn; d->d_tag != DT_NULL; d++) {
+		switch (d->d_tag) {
+		case DT_RELA:
+			rela = (void *)(d->d_un.d_ptr + p2v_offset);
+			break;
+		case DT_RELASZ:
+			relasize = d->d_un.d_val;
+			break;
+		case DT_RELR:
+			relr = (void *)(d->d_un.d_ptr + p2v_offset);
+			break;
+		case DT_RELRSZ:
+			relrsize = d->d_un.d_val;
+			break;
+		case DT_REL:
+			rel = (void *)(d->d_un.d_ptr + p2v_offset);
+			break;
+		case DT_RELSZ:
+			relsize = d->d_un.d_val;
+			break;
+		}
+	}
+
+	for (int i = 0; i < relasize / sizeof(*rela); i++) {
+		place = (unsigned long *)(rela[i].r_offset + p2v_offset);
+		*place += va_shift;
+	}
+
+	for (int i = 0; i < relrsize / sizeof(*relr); i++) {
+		if ((relr[i] & 1) == 0) {
+			place = (unsigned long *)(relr[i] + p2v_offset);
+			*place++ += va_shift;
+			continue;
+		}
+
+		for (unsigned long *p = place, r = relr[i] >> 1; r; p++, r >>= 1)
+			if (r & 1)
+				*p += va_shift;
+		place += 8 * sizeof(*relr) - 1;
+	}
+
+	for (int i = 0; i < relsize / sizeof(*rel); i++) {
+		place = (unsigned long *)(rel[i].r_offset + p2v_offset);
+		*place += va_shift;
+	}
+
+}
+
+static size_t parse_elf(void *output, u64 va_shift)
 {
 #ifdef CONFIG_X86_64
 	Elf64_Ehdr ehdr;
@@ -320,6 +381,12 @@ static size_t parse_elf(void *output)
 				dest += (unsigned long)output - LOAD_PHYSICAL_ADDR;
 			memmove(dest, output + phdr->p_offset, phdr->p_filesz);
 			break;
+		case PT_DYNAMIC:
+			if (!va_shift)
+				break;
+			dest = (void *)(output + phdr->p_paddr - LOAD_PHYSICAL_ADDR);
+			handle_dynamic(dest, (unsigned long)dest - phdr->p_vaddr, va_shift);
+			break;
 		default: /* Ignore other PT_* */ break;
 		}
 	}
@@ -351,7 +418,9 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
 			 NULL, error) < 0)
 		return ULONG_MAX;
 
-	entry = parse_elf(outbuf);
+	if (IS_ENABLED(CONFIG_X86_32))
+		virt_addr = (unsigned long)outbuf;
+	entry = parse_elf(outbuf, virt_addr - LOAD_PHYSICAL_ADDR);
 	handle_relocations(outbuf, output_len, virt_addr);
 
 	return entry;
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index 819ded2d39de..868cd67f0ea7 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -103,6 +103,9 @@ typedef __u16	Elf64_Versym;
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
 #define DT_ENCODING	32
+#define DT_RELRSZ	35
+#define DT_RELR		36
+#define DT_RELRENT	37
 #define OLD_DT_LOOS	0x60000000
 #define DT_LOOS		0x6000000d
 #define DT_HIOS		0x6ffff000
-- 
2.47.3


  parent reply	other threads:[~2026-01-08  9:28 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-08  9:25 [RFC/RFT PATCH 00/19] Link the relocatable x86 kernel as PIE Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 01/19] x86/idt: Move idt_table to __ro_after_init section Ard Biesheuvel
2026-01-22 13:08   ` Borislav Petkov
2026-01-22 13:48     ` Ard Biesheuvel
2026-01-22 13:58       ` Borislav Petkov
2026-01-22 14:09         ` Ard Biesheuvel
2026-01-22 14:16           ` Borislav Petkov
2026-01-22 14:20             ` Ard Biesheuvel
2026-01-22 14:25               ` Borislav Petkov
2026-01-08  9:25 ` [RFC/RFT PATCH 02/19] x86/sev: Don't emit BSS_DECRYPT section unless it is in use Ard Biesheuvel
2026-01-31 14:09   ` [tip: x86/sev] x86/sev: Don't emit BSS_DECRYPTED " tip-bot2 for Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 03/19] x86: Combine .data with .bss in kernel mapping Ard Biesheuvel
2026-03-06 19:07   ` Borislav Petkov
2026-03-09 14:11     ` Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 04/19] x86: Make the 64-bit bzImage always physically relocatable Ard Biesheuvel
2026-01-12  4:01   ` H. Peter Anvin
2026-01-12 10:47     ` David Laight
2026-01-12 12:06       ` H. Peter Anvin
2026-01-08  9:25 ` [RFC/RFT PATCH 05/19] x86/efistub: Simplify early remapping of kernel text Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 06/19] alloc_tag: Use __ prefixed ELF section names Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 07/19] tools/objtool: Treat indirect ftrace calls as direct calls Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 08/19] x86: Use PIE codegen for the relocatable 64-bit kernel Ard Biesheuvel
2026-01-09 21:34   ` Jan Engelhardt
2026-01-09 22:07     ` Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 09/19] x86/pm-trace: Use RIP-relative accesses for .tracedata Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 10/19] x86/kvm: Use RIP-relative addressing Ard Biesheuvel
2026-01-20 17:04   ` Sean Christopherson
2026-01-20 19:43     ` David Laight
2026-01-20 20:54       ` Ard Biesheuvel
2026-01-20 22:00         ` David Laight
2026-01-08  9:25 ` [RFC/RFT PATCH 11/19] x86/rethook: Use RIP-relative reference for fake return address Ard Biesheuvel
2026-01-08 12:08   ` David Laight
2026-01-08 12:10     ` Ard Biesheuvel
2026-01-08 12:19       ` Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 12/19] x86/sync_core: Use RIP-relative addressing Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 13/19] x86/entry_64: " Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 14/19] x86/hibernate: Prefer RIP-relative accesses Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 15/19] x64/acpi: Use PIC-compatible references in wakeup_64.S Ard Biesheuvel
2026-01-09  5:01   ` Brian Gerst
2026-01-09  7:59     ` Ard Biesheuvel
2026-01-09 11:46       ` Brian Gerst
2026-01-09 12:09         ` Ard Biesheuvel
2026-01-09 12:10           ` Ard Biesheuvel
2026-01-09 12:51             ` Brian Gerst
2026-01-08  9:25 ` [RFC/RFT PATCH 16/19] x86/kexec: Use 64-bit wide absolute reference from relocated code Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 17/19] x86/head64: Avoid absolute references in startup asm Ard Biesheuvel
2026-01-08  9:25 ` Ard Biesheuvel [this message]
2026-01-08  9:25 ` [RFC/RFT PATCH 19/19] x86/kernel: Switch to PIE linking for the relocatable kernel Ard Biesheuvel
2026-01-08 16:35 ` [RFC/RFT PATCH 00/19] Link the relocatable x86 kernel as PIE Alexander Lobakin
2026-01-09  0:36 ` H. Peter Anvin
2026-01-09  9:21   ` Ard Biesheuvel
2026-01-14 18:16     ` Kees Cook
2026-01-20 20:45       ` H. Peter Anvin
2026-01-21  8:56         ` 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=20260108092526.28586-39-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=jpoimboe@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=ubizjak@gmail.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.