Skip to content

Commit 5c6808d

Browse files
ardbiesheuveljgross1
authored andcommitted
x86/pvh: Avoid absolute symbol references in .head.text
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> Message-ID: <20241009160438.3884381-12-ardb+git@google.com> Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent 223abe9 commit 5c6808d

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

arch/x86/platform/pvh/head.S

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
.code32
88
.text
9+
#ifdef CONFIG_X86_32
910
#define _pa(x) ((x) - __START_KERNEL_map)
11+
#endif
1012
#define rva(x) ((x) - pvh_start_xen)
1113

1214
#include <linux/elfnote.h>
@@ -72,8 +74,7 @@ SYM_CODE_START(pvh_start_xen)
7274
movl $0, %esp
7375

7476
leal rva(gdt)(%ebp), %eax
75-
leal rva(gdt_start)(%ebp), %ecx
76-
movl %ecx, 2(%eax)
77+
addl %eax, 2(%eax)
7778
lgdt (%eax)
7879

7980
mov $PVH_DS_SEL,%eax
@@ -103,10 +104,23 @@ SYM_CODE_START(pvh_start_xen)
103104
btsl $_EFER_LME, %eax
104105
wrmsr
105106

107+
/*
108+
* Reuse the non-relocatable symbol emitted for the ELF note to
109+
* subtract the build time physical address of pvh_start_xen() from
110+
* its actual runtime address, without relying on absolute 32-bit ELF
111+
* relocations, as these are not supported by the linker when running
112+
* in -pie mode, and should be avoided in .head.text in general.
113+
*/
106114
mov %ebp, %ebx
107-
subl $_pa(pvh_start_xen), %ebx /* offset */
115+
subl rva(xen_elfnote_phys32_entry)(%ebp), %ebx
108116
jz .Lpagetable_done
109117

118+
/*
119+
* Store the resulting load offset in phys_base. __pa() needs
120+
* phys_base set to calculate the hypercall page in xen_pvh_init().
121+
*/
122+
movl %ebx, rva(phys_base)(%ebp)
123+
110124
/* Fixup page-tables for relocation. */
111125
leal rva(pvh_init_top_pgt)(%ebp), %edi
112126
movl $PTRS_PER_PGD, %ecx
@@ -165,14 +179,6 @@ SYM_CODE_START(pvh_start_xen)
165179
xor %edx, %edx
166180
wrmsr
167181

168-
/*
169-
* Calculate load offset and store in phys_base. __pa() needs
170-
* phys_base set to calculate the hypercall page in xen_pvh_init().
171-
*/
172-
movq %rbp, %rbx
173-
subq $_pa(pvh_start_xen), %rbx
174-
movq %rbx, phys_base(%rip)
175-
176182
/* Call xen_prepare_pvh() via the kernel virtual mapping */
177183
leaq xen_prepare_pvh(%rip), %rax
178184
subq phys_base(%rip), %rax
@@ -218,7 +224,7 @@ SYM_CODE_END(pvh_start_xen)
218224
.balign 8
219225
SYM_DATA_START_LOCAL(gdt)
220226
.word gdt_end - gdt_start - 1
221-
.long _pa(gdt_start) /* x86-64 will overwrite if relocated. */
227+
.long gdt_start - gdt
222228
.word 0
223229
SYM_DATA_END(gdt)
224230
SYM_DATA_START_LOCAL(gdt_start)

0 commit comments

Comments
 (0)