mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
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>
This commit is contained in:
parent
223abe96ac
commit
5c6808d1a9
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user