* [PATCH v2 0/5] x86/xen: Drop absolute references from startup code
@ 2024-09-30 7:15 Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 1/5] x86/pvh: Call C code via the kernel virtual mapping Ard Biesheuvel
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
This series was broken out of the series I sent last week [0], after
Jason pointed out that my Xen startup code changes conflict with his
changes to make the PVH startup code position independent.
Jason's work reduces the delta of my changes, and given that my other
series will likely advance at a much slower pace, the Xen changes are
presented here so they can be merged independently.
The end result after applying this series (see below) is that there are
no longer any Xen-related absolute relocations that need to be applied
to .head.text, which carries code that may be invoked from the 1:1
mapping of memory before the kernel virtual mapping is up. The use of
absolute references in this code section has resulted in a few boot
issues that were very hard to track down (Clang built kernels running
under SEV-SNP in particular, which does not provide the best debug
experience).
Even though the occurrences in the Xen startup code were fine, there is
now a lot of C code emitted into .head.text as well, and so it would be
helpful to teach objtool to reject absolute references entirely in this
section (or rely on the linker for that). Therefore, not relying on them
in the first place is a step towards that goal.
Changes wrt [0]:
- add Jason's Rb to patch #1
- rebase onto xen/tip's linux-next branch
- split out fix for GDT descriptor size field
- add patch to remove the zeroing of phys_base, which is no longer
needed
- use a 32-bit field for XEN_ELFNOTE_PHYS32_ENTRY, and use its contents
to obtain the build time physical address of pvh_startup_xen()
Changes since v1 [1]:
- add Jason's Rb to patches #2, #3 and #5
- drop the use of a 32-bit field for the ELF note- QEMU reads a u64 and
so the top word needs to remain 0x0
- tweak #ifdefs in patch #4 so the hypercall_page linker symbol does not
depend on CONFIG_XEN_PV
- rebase onto v6.12-rc1
[0] https://lore.kernel.org/all/20240925150059.3955569-30-ardb+git@google.com
[1] https://lore.kernel.org/all/20240926104113.80146-7-ardb+git@google.com/
Relocation section '.rela.head.text' at offset 0xb428 contains 15 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000018 000800000002 R_X86_64_PC32 0000000000000000 .init.data + 18
00000000002f 000e00000002 R_X86_64_PC32 0000000000000000 pvh_start_info + 2f
000000000037 000f00000002 R_X86_64_PC32 0000000000000000 pvh_start_info_sz + 37
000000000042 000800000002 R_X86_64_PC32 0000000000000000 .init.data + 4092
000000000060 001000000002 R_X86_64_PC32 000000000000002c xen_elfnote_phys3[...] + 60
000000000068 001100000002 R_X86_64_PC32 0000000000000000 phys_base + 68
00000000006e 001200000002 R_X86_64_PC32 0000000000005000 pvh_init_top_pgt + 6e
000000000089 001300000002 R_X86_64_PC32 0000000000006000 pvh_level3_ident_pgt + 89
000000000091 001400000002 R_X86_64_PC32 0000000000008000 pvh_level3_kernel_pgt + 91
0000000000a3 001500000002 R_X86_64_PC32 0000000000009000 pvh_level2_kernel_pgt + a3
0000000000be 001200000002 R_X86_64_PC32 0000000000005000 pvh_init_top_pgt + be
0000000000de 000800000002 R_X86_64_PC32 0000000000000000 .init.data + 1c
0000000000e9 001600000002 R_X86_64_PC32 0000000000000000 xen_prepare_pvh - 4
0000000000f8 001700000002 R_X86_64_PC32 0000000000000000 pvh_bootparams - 4
0000000000fd 001800000004 R_X86_64_PLT32 0000000000000000 startup_64 - 4
Relocation section '.rela.note.Xen' at offset 0xb668 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
00000000002c 001a00000002 R_X86_64_PC32 0000000000000000 xen_elfnote_phys3[...] + 0
Cc: Jason Andryuk <jason.andryuk@amd.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: x86@kernel.org
Cc: xen-devel@lists.xenproject.org
Ard Biesheuvel (5):
x86/pvh: Call C code via the kernel virtual mapping
x86/pvh: Use correct size value in GDT descriptor
x86/pvh: Omit needless clearing of phys_base
x86/xen: Avoid relocatable quantities in Xen ELF notes
x86/pvh: Avoid absolute symbol references in .head.text
arch/x86/kernel/vmlinux.lds.S | 13 +++++
arch/x86/platform/pvh/head.S | 50 +++++++++++---------
arch/x86/tools/relocs.c | 1 +
arch/x86/xen/xen-head.S | 6 ++-
4 files changed, 46 insertions(+), 24 deletions(-)
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/5] x86/pvh: Call C code via the kernel virtual mapping
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
@ 2024-09-30 7:15 ` Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 2/5] x86/pvh: Use correct size value in GDT descriptor Ard Biesheuvel
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
Calling C code via a different mapping than it was linked at is
problematic, because the compiler assumes that RIP-relative and absolute
symbol references are interchangeable. GCC in particular may use
RIP-relative per-CPU variable references even when not using -fpic.
So call xen_prepare_pvh() via its kernel virtual mapping on x86_64, so
that those RIP-relative references produce the correct values. This
matches the pre-existing behavior for i386, which also invokes
xen_prepare_pvh() via the kernel virtual mapping before invoking
startup_32 with paging disabled again.
Fixes: 7243b93345f7 ("xen/pvh: Bootstrap PVH guest")
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/platform/pvh/head.S | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index 64fca49cd88f..ce4fd8d33da4 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -172,7 +172,14 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
movq %rbp, %rbx
subq $_pa(pvh_start_xen), %rbx
movq %rbx, phys_base(%rip)
- call xen_prepare_pvh
+
+ /* Call xen_prepare_pvh() via the kernel virtual mapping */
+ leaq xen_prepare_pvh(%rip), %rax
+ subq phys_base(%rip), %rax
+ addq $__START_KERNEL_map, %rax
+ ANNOTATE_RETPOLINE_SAFE
+ call *%rax
+
/*
* Clear phys_base. __startup_64 will *add* to its value,
* so reset to 0.
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/5] x86/pvh: Use correct size value in GDT descriptor
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 1/5] x86/pvh: Call C code via the kernel virtual mapping Ard Biesheuvel
@ 2024-09-30 7:15 ` Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 3/5] x86/pvh: Omit needless clearing of phys_base Ard Biesheuvel
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
The limit field in a GDT descriptor is an inclusive bound, and therefore
one less than the size of the covered range.
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/platform/pvh/head.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index ce4fd8d33da4..5a196fb3ebd8 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -224,7 +224,7 @@ SYM_CODE_END(pvh_start_xen)
.section ".init.data","aw"
.balign 8
SYM_DATA_START_LOCAL(gdt)
- .word gdt_end - gdt_start
+ .word gdt_end - gdt_start - 1
.long _pa(gdt_start) /* x86-64 will overwrite if relocated. */
.word 0
SYM_DATA_END(gdt)
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/5] x86/pvh: Omit needless clearing of phys_base
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 1/5] x86/pvh: Call C code via the kernel virtual mapping Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 2/5] x86/pvh: Use correct size value in GDT descriptor Ard Biesheuvel
@ 2024-09-30 7:15 ` Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 5/5] x86/pvh: Avoid absolute symbol references in .head.text Ard Biesheuvel
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
Since commit
d9ec1158056b ("x86/boot/64: Use RIP_REL_REF() to assign 'phys_base'")
phys_base is assigned directly rather than added to, so it is no longer
necessary to clear it after use.
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/platform/pvh/head.S | 7 -------
1 file changed, 7 deletions(-)
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index 5a196fb3ebd8..7ca51a4da217 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -180,13 +180,6 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
ANNOTATE_RETPOLINE_SAFE
call *%rax
- /*
- * Clear phys_base. __startup_64 will *add* to its value,
- * so reset to 0.
- */
- xor %rbx, %rbx
- movq %rbx, phys_base(%rip)
-
/* startup_64 expects boot_params in %rsi. */
lea pvh_bootparams(%rip), %rsi
jmp startup_64
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
` (2 preceding siblings ...)
2024-09-30 7:15 ` [PATCH v2 3/5] x86/pvh: Omit needless clearing of phys_base Ard Biesheuvel
@ 2024-09-30 7:15 ` Ard Biesheuvel
2024-10-02 21:25 ` Jason Andryuk
2024-09-30 7:15 ` [PATCH v2 5/5] x86/pvh: Avoid absolute symbol references in .head.text Ard Biesheuvel
4 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
Xen puts virtual and physical addresses into ELF notes that are treated
by the linker as relocatable by default. Doing so is not only pointless,
given that the ELF notes are only intended for consumption by Xen before
the kernel boots. It is also a KASLR leak, given that the kernel's ELF
notes are exposed via the world readable /sys/kernel/notes.
So emit these constants in a way that prevents the linker from marking
them as relocatable. This involves place-relative relocations (which
subtract their own virtual address from the symbol value) and linker
provided absolute symbols that add the address of the place to the
desired value.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/kernel/vmlinux.lds.S | 13 +++++++++++++
arch/x86/platform/pvh/head.S | 6 +++---
arch/x86/tools/relocs.c | 1 +
arch/x86/xen/xen-head.S | 6 ++++--
4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 6726be89b7a6..2b7c8c14c6fd 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -527,3 +527,16 @@ INIT_PER_CPU(irq_stack_backing_store);
#endif
#endif /* CONFIG_X86_64 */
+
+#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PV
+xen_elfnote_entry_offset =
+ ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen);
+#endif
+xen_elfnote_hypercall_page_offset =
+ ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page);
+#endif
+#ifdef CONFIG_PVH
+xen_elfnote_phys32_entry_offset =
+ ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET);
+#endif
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index 7ca51a4da217..2b0d887e0872 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -52,7 +52,7 @@
#define PVH_CS_SEL (PVH_GDT_ENTRY_CS * 8)
#define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8)
-SYM_CODE_START_LOCAL(pvh_start_xen)
+SYM_CODE_START(pvh_start_xen)
UNWIND_HINT_END_OF_STACK
cld
@@ -300,5 +300,5 @@ SYM_DATA_END(pvh_level2_kernel_pgt)
.long KERNEL_IMAGE_SIZE - 1)
#endif
- ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
- _ASM_PTR (pvh_start_xen - __START_KERNEL_map))
+ ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .global xen_elfnote_phys32_entry;
+ xen_elfnote_phys32_entry: _ASM_PTR xen_elfnote_phys32_entry_offset - .)
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index c101bed61940..3ede19ca8432 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -56,6 +56,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
[S_ABS] =
"^(xen_irq_disable_direct_reloc$|"
"xen_save_fl_direct_reloc$|"
+ "xen_elfnote_.+_offset$|"
"VDSO|"
"__kcfi_typeid_|"
"__crc_)",
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 758bcd47b72d..3deaae3601f7 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -94,7 +94,8 @@ SYM_CODE_END(xen_cpu_bringup_again)
ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __START_KERNEL_map)
/* Map the p2m table to a 512GB-aligned user address. */
ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad (PUD_SIZE * PTRS_PER_PUD))
- ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen)
+ ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .globl xen_elfnote_entry;
+ xen_elfnote_entry: _ASM_PTR xen_elfnote_entry_offset - .)
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .ascii "!writable_page_tables")
ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes")
ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
@@ -115,7 +116,8 @@ SYM_CODE_END(xen_cpu_bringup_again)
#else
# define FEATURES_DOM0 0
#endif
- ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
+ ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .globl xen_elfnote_hypercall_page;
+ xen_elfnote_hypercall_page: _ASM_PTR xen_elfnote_hypercall_page_offset - .)
ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
.long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 5/5] x86/pvh: Avoid absolute symbol references in .head.text
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
` (3 preceding siblings ...)
2024-09-30 7:15 ` [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes Ard Biesheuvel
@ 2024-09-30 7:15 ` Ard Biesheuvel
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-09-30 7:15 UTC (permalink / raw)
To: linux-kernel
Cc: Ard Biesheuvel, Jason Andryuk, Juergen Gross, Boris Ostrovsky,
x86, xen-devel
From: Ard Biesheuvel <ardb@kernel.org>
The .head.text section contains code that may execute from a different
address than it was linked at. This is fragile, given that the x86 ABI
can refer to global symbols via absolute or relative references, and the
toolchain assumes that these are interchangeable, which they are not in
this particular case.
For this reason, all absolute symbol references are being removed from
code that is emitted into .head.text. Subsequently, build time
validation may be added that ensures that no absolute ELF relocations
exist at all in that ELF section.
In the case of the PVH code, the absolute references are in 32-bit code,
which gets emitted with R_X86_64_32 relocations, and these are even more
problematic going forward, as it prevents running the linker in PIE
mode.
So update the 64-bit code to avoid _pa(), and to only rely on relative
symbol references: these are always 32-bits wide, even in 64-bit code,
and are resolved by the linker at build time.
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/platform/pvh/head.S | 30 ++++++++++++--------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index 2b0d887e0872..cf89b2385c5a 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -6,7 +6,9 @@
.code32
.text
+#ifdef CONFIG_X86_32
#define _pa(x) ((x) - __START_KERNEL_map)
+#endif
#define rva(x) ((x) - pvh_start_xen)
#include <linux/elfnote.h>
@@ -72,8 +74,7 @@ SYM_CODE_START(pvh_start_xen)
movl $0, %esp
leal rva(gdt)(%ebp), %eax
- leal rva(gdt_start)(%ebp), %ecx
- movl %ecx, 2(%eax)
+ addl %eax, 2(%eax)
lgdt (%eax)
mov $PVH_DS_SEL,%eax
@@ -103,10 +104,23 @@ SYM_CODE_START(pvh_start_xen)
btsl $_EFER_LME, %eax
wrmsr
+ /*
+ * Reuse the non-relocatable symbol emitted for the ELF note to
+ * subtract the build time physical address of pvh_start_xen() from
+ * its actual runtime address, without relying on absolute 32-bit ELF
+ * relocations, as these are not supported by the linker when running
+ * in -pie mode, and should be avoided in .head.text in general.
+ */
mov %ebp, %ebx
- subl $_pa(pvh_start_xen), %ebx /* offset */
+ subl rva(xen_elfnote_phys32_entry)(%ebp), %ebx
jz .Lpagetable_done
+ /*
+ * Store the resulting load offset in phys_base. __pa() needs
+ * phys_base set to calculate the hypercall page in xen_pvh_init().
+ */
+ movl %ebx, rva(phys_base)(%ebp)
+
/* Fixup page-tables for relocation. */
leal rva(pvh_init_top_pgt)(%ebp), %edi
movl $PTRS_PER_PGD, %ecx
@@ -165,14 +179,6 @@ SYM_CODE_START(pvh_start_xen)
xor %edx, %edx
wrmsr
- /*
- * Calculate load offset and store in phys_base. __pa() needs
- * phys_base set to calculate the hypercall page in xen_pvh_init().
- */
- movq %rbp, %rbx
- subq $_pa(pvh_start_xen), %rbx
- movq %rbx, phys_base(%rip)
-
/* Call xen_prepare_pvh() via the kernel virtual mapping */
leaq xen_prepare_pvh(%rip), %rax
subq phys_base(%rip), %rax
@@ -218,7 +224,7 @@ SYM_CODE_END(pvh_start_xen)
.balign 8
SYM_DATA_START_LOCAL(gdt)
.word gdt_end - gdt_start - 1
- .long _pa(gdt_start) /* x86-64 will overwrite if relocated. */
+ .long gdt_start - gdt
.word 0
SYM_DATA_END(gdt)
SYM_DATA_START_LOCAL(gdt_start)
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes
2024-09-30 7:15 ` [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes Ard Biesheuvel
@ 2024-10-02 21:25 ` Jason Andryuk
2024-10-03 7:49 ` Ard Biesheuvel
0 siblings, 1 reply; 8+ messages in thread
From: Jason Andryuk @ 2024-10-02 21:25 UTC (permalink / raw)
To: Ard Biesheuvel, linux-kernel
Cc: Ard Biesheuvel, Juergen Gross, Boris Ostrovsky, x86, xen-devel
On 2024-09-30 03:15, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
>
> Xen puts virtual and physical addresses into ELF notes that are treated
> by the linker as relocatable by default. Doing so is not only pointless,
> given that the ELF notes are only intended for consumption by Xen before
> the kernel boots. It is also a KASLR leak, given that the kernel's ELF
> notes are exposed via the world readable /sys/kernel/notes.
>
> So emit these constants in a way that prevents the linker from marking
> them as relocatable. This involves place-relative relocations (which
> subtract their own virtual address from the symbol value) and linker
> provided absolute symbols that add the address of the place to the
> desired value.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
The generated values look ok.
> ---
> arch/x86/kernel/vmlinux.lds.S | 13 +++++++++++++
> arch/x86/platform/pvh/head.S | 6 +++---
> arch/x86/tools/relocs.c | 1 +
> arch/x86/xen/xen-head.S | 6 ++++--
> 4 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> index 6726be89b7a6..2b7c8c14c6fd 100644
> --- a/arch/x86/kernel/vmlinux.lds.S
> +++ b/arch/x86/kernel/vmlinux.lds.S
> @@ -527,3 +527,16 @@ INIT_PER_CPU(irq_stack_backing_store);
> #endif
>
> #endif /* CONFIG_X86_64 */
> +
> +#ifdef CONFIG_XEN
> +#ifdef CONFIG_XEN_PV
> +xen_elfnote_entry_offset =
> + ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen);
> +#endif
> +xen_elfnote_hypercall_page_offset =
> + ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page);
> +#endif
> +#ifdef CONFIG_PVH
> +xen_elfnote_phys32_entry_offset =
> + ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET);
> +#endif
It seems to me, these aren't really offsets, but instead an address + value.
> diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
> index 7ca51a4da217..2b0d887e0872 100644
> --- a/arch/x86/platform/pvh/head.S
> +++ b/arch/x86/platform/pvh/head.S
> @@ -300,5 +300,5 @@ SYM_DATA_END(pvh_level2_kernel_pgt)
> .long KERNEL_IMAGE_SIZE - 1)
> #endif
>
> - ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
> - _ASM_PTR (pvh_start_xen - __START_KERNEL_map))
> + ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .global xen_elfnote_phys32_entry;
> + xen_elfnote_phys32_entry: _ASM_PTR xen_elfnote_phys32_entry_offset - .)
So here you have `address + value - address` to put the desired value in
the elf note?
Regards,
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes
2024-10-02 21:25 ` Jason Andryuk
@ 2024-10-03 7:49 ` Ard Biesheuvel
0 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2024-10-03 7:49 UTC (permalink / raw)
To: Jason Andryuk
Cc: Ard Biesheuvel, linux-kernel, Juergen Gross, Boris Ostrovsky, x86,
xen-devel
On Wed, 2 Oct 2024 at 23:25, Jason Andryuk <jason.andryuk@amd.com> wrote:
>
> On 2024-09-30 03:15, Ard Biesheuvel wrote:
> > From: Ard Biesheuvel <ardb@kernel.org>
> >
> > Xen puts virtual and physical addresses into ELF notes that are treated
> > by the linker as relocatable by default. Doing so is not only pointless,
> > given that the ELF notes are only intended for consumption by Xen before
> > the kernel boots. It is also a KASLR leak, given that the kernel's ELF
> > notes are exposed via the world readable /sys/kernel/notes.
> >
> > So emit these constants in a way that prevents the linker from marking
> > them as relocatable. This involves place-relative relocations (which
> > subtract their own virtual address from the symbol value) and linker
> > provided absolute symbols that add the address of the place to the
> > desired value.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> Tested-by: Jason Andryuk <jason.andryuk@amd.com>
>
> The generated values look ok.
>
> > ---
> > arch/x86/kernel/vmlinux.lds.S | 13 +++++++++++++
> > arch/x86/platform/pvh/head.S | 6 +++---
> > arch/x86/tools/relocs.c | 1 +
> > arch/x86/xen/xen-head.S | 6 ++++--
> > 4 files changed, 21 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> > index 6726be89b7a6..2b7c8c14c6fd 100644
> > --- a/arch/x86/kernel/vmlinux.lds.S
> > +++ b/arch/x86/kernel/vmlinux.lds.S
> > @@ -527,3 +527,16 @@ INIT_PER_CPU(irq_stack_backing_store);
> > #endif
> >
> > #endif /* CONFIG_X86_64 */
> > +
> > +#ifdef CONFIG_XEN
> > +#ifdef CONFIG_XEN_PV
> > +xen_elfnote_entry_offset =
> > + ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen);
> > +#endif
> > +xen_elfnote_hypercall_page_offset =
> > + ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page);
> > +#endif
> > +#ifdef CONFIG_PVH
> > +xen_elfnote_phys32_entry_offset =
> > + ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET);
> > +#endif
>
> It seems to me, these aren't really offsets, but instead an address + value.
>
Indeed. So xen_elfnote_phys32_entry_value would probably be a better name.
> > diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
> > index 7ca51a4da217..2b0d887e0872 100644
> > --- a/arch/x86/platform/pvh/head.S
> > +++ b/arch/x86/platform/pvh/head.S
>
> > @@ -300,5 +300,5 @@ SYM_DATA_END(pvh_level2_kernel_pgt)
> > .long KERNEL_IMAGE_SIZE - 1)
> > #endif
> >
> > - ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
> > - _ASM_PTR (pvh_start_xen - __START_KERNEL_map))
> > + ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .global xen_elfnote_phys32_entry;
> > + xen_elfnote_phys32_entry: _ASM_PTR xen_elfnote_phys32_entry_offset - .)
>
> So here you have `address + value - address` to put the desired value in
> the elf note?
>
Exactly. The assembler emits a relative relocation, and the linker
resolves it at build time.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-10-03 7:49 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-30 7:15 [PATCH v2 0/5] x86/xen: Drop absolute references from startup code Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 1/5] x86/pvh: Call C code via the kernel virtual mapping Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 2/5] x86/pvh: Use correct size value in GDT descriptor Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 3/5] x86/pvh: Omit needless clearing of phys_base Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 4/5] x86/xen: Avoid relocatable quantities in Xen ELF notes Ard Biesheuvel
2024-10-02 21:25 ` Jason Andryuk
2024-10-03 7:49 ` Ard Biesheuvel
2024-09-30 7:15 ` [PATCH v2 5/5] x86/pvh: Avoid absolute symbol references in .head.text Ard Biesheuvel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox