[PATCH 3/3] x86/boot: Perform GOT relocation before calling EFI stub

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



While the EFI stub code does not generally require a GOT, it is very
easy to write code that would require a GOT with an old toolchain, but
that modern toolchains optimize to eliminate the GOT references. This
can lead to unexpected crashes if the kernel is built with an older
toolchain.

To avoid potential issues, move the efi_pe_entry back to assembler, and
relocate the GOT if present before calling any C code.

Signed-off-by: Arvind Sankar <nivedita@xxxxxxxxxxxx>
---
 arch/x86/boot/compressed/eboot.c   |  4 ++--
 arch/x86/boot/compressed/head_32.S | 23 ++++++++++++++++++++++-
 arch/x86/boot/compressed/head_64.S | 18 ++++++++++++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ab3a40283db7..b62f957274aa 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -356,8 +356,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
  * need to create one ourselves (usually the bootloader would create
  * one for us).
  */
-efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
-				   efi_system_table_t *sys_table_arg)
+efi_status_t efi_entry(efi_handle_t handle,
+		       efi_system_table_t *sys_table_arg)
 {
 	struct boot_params *boot_params;
 	struct apm_bios_info *bi;
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 973ac0b51af5..171947ae5b8c 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -145,9 +145,29 @@ SYM_FUNC_START(startup_32)
 SYM_FUNC_END(startup_32)
 
 #ifdef CONFIG_EFI_STUB
+
+SYM_FUNC_START(efi_pe_entry)
+	/* Adjust the GOT */
+	/* Don't clobber EBX as we may return to firmware in case of error */
+	pushl	%ebx
+	call	1f
+1:	popl	%ebx
+	subl	$1b, %ebx
+	call	.Ladjust_got
+	popl	%ebx
+	/* Transfer control to C entry */
+	jmp	efi_entry
+SYM_FUNC_END(efi_pe_entry)
+
 SYM_FUNC_START(efi32_stub_entry)
 SYM_FUNC_START_ALIAS(efi_stub_entry)
-	add	$0x4, %esp
+	/* We cannot return from here */
+	addl	$0x4, %esp
+	/* Adjust the GOT */
+	call	1f
+1:	popl	%ebx
+	subl	$1b, %ebx
+	call	.Ladjust_got
 	call	efi_main
 	movl	%eax, %esi
 	movl	BP_code32_start(%esi), %eax
@@ -155,6 +175,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
 	jmp	*%eax
 SYM_FUNC_END(efi32_stub_entry)
 SYM_FUNC_END_ALIAS(efi_stub_entry)
+
 #endif
 
 	.text
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 1464d8d0ec66..5a295d41a7a8 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -421,9 +421,26 @@ trampoline_return:
 SYM_CODE_END(startup_64)
 
 #ifdef CONFIG_EFI_STUB
+
+SYM_FUNC_START(efi_pe_entry)
+	/* Convert arguments to SysV ABI */
+	movq	%rcx, %rdi
+	movq	%rdx, %rsi
+	/* Adjust the GOT */
+	call	.Ladjust_got
+	/* Transfer control to C entry */
+	jmp	efi_entry
+SYM_FUNC_END(efi_pe_entry)
+
 	.org 0x390
 SYM_FUNC_START(efi64_stub_entry)
 SYM_FUNC_START_ALIAS(efi_stub_entry)
+	/* We cannot return from here */
+	addq	$8, %rsp
+	/* Adjust the GOT */
+	pushq	%rdx
+	call	.Ladjust_got
+	popq	%rdx
 	and	$~0xf, %rsp			/* realign the stack */
 	call	efi_main
 	movq	%rax,%rsi
@@ -432,6 +449,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
 	jmp	*%rax
 SYM_FUNC_END(efi64_stub_entry)
 SYM_FUNC_END_ALIAS(efi_stub_entry)
+
 #endif
 
 	.text
-- 
2.24.1




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux