Blob Blame History Raw
From 4e78921ba4dd0aca1cc89168f45039add4183f8e Mon Sep 17 00:00:00 2001
From: Gen Zhang <blackgod016574@gmail.com>
Date: Sat, 25 May 2019 13:25:58 +0200
Subject: [PATCH] efi/x86/Add missing error handling to old_memmap 1:1 mapping code
Git-commit: 4e78921ba4dd0aca1cc89168f45039add4183f8e
Patch-mainline: v5.2-rc3
References: CVE-2019-12380,bsc#1136598

The old_memmap flow in efi_call_phys_prolog() performs numerous memory
allocations, and either does not check for failure at all, or it does
but fails to propagate it back to the caller, which may end up calling
into the firmware with an incomplete 1:1 mapping.

So let's fix this by returning NULL from efi_call_phys_prolog() on
memory allocation failures only, and by handling this condition in the
caller. Also, clean up any half baked sets of page tables that we may
have created before returning with a NULL return value.

Note that any failure at this level will trigger a panic() two levels
up, so none of this makes a huge difference, but it is a nice cleanup
nonetheless.

[ardb: update commit log, add efi_call_phys_epilog() call on error path]

Signed-off-by: Gen Zhang <blackgod016574@gmail.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rob Bradford <robert.bradford@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20190525112559.7917-2-ard.biesheuvel@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 arch/x86/platform/efi/efi.c    |    2 ++
 arch/x86/platform/efi/efi_64.c |   10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -85,6 +85,8 @@ static efi_status_t __init phys_efi_set_
 	pgd_t *save_pgd;
 
 	save_pgd = efi_call_phys_prolog();
+	if (!save_pgd)
+		return EFI_ABORTED;
 
 	/* Disable interrupts around EFI calls: */
 	local_irq_save(flags);
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -90,6 +90,8 @@ pgd_t * __init efi_call_phys_prolog(void
 
 	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
 	save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL);
+	if (!save_pgd)
+		return NULL;
 
 	/*
 	 * Build 1:1 identity mapping for efi=old_map usage. Note that
@@ -108,7 +110,7 @@ pgd_t * __init efi_call_phys_prolog(void
 		p4d = p4d_alloc(&init_mm, pgd_efi, addr_pgd);
 		if (!p4d) {
 			pr_err("Failed to allocate p4d table!\n");
-			goto out;
+			goto error;
 		}
 
 		for (i = 0; i < PTRS_PER_P4D; i++) {
@@ -118,7 +120,7 @@ pgd_t * __init efi_call_phys_prolog(void
 			pud = pud_alloc(&init_mm, p4d_efi, addr_p4d);
 			if (!pud) {
 				pr_err("Failed to allocate pud table!\n");
-				goto out;
+				goto error;
 			}
 
 			for (j = 0; j < PTRS_PER_PUD; j++) {
@@ -141,6 +143,10 @@ out:
 	__flush_tlb_all();
 
 	return save_pgd;
+
+error:
+	efi_call_phys_epilog(save_pgd);
+	return NULL;
 }
 
 void __init efi_call_phys_epilog(pgd_t *save_pgd)