efi/x86/Add missing error handling to old_memmap 1:1 mapping code
authorGen Zhang <blackgod016574@gmail.com>
Sat, 25 May 2019 11:25:58 +0000 (13:25 +0200)
committerIngo Molnar <mingo@kernel.org>
Sat, 25 May 2019 11:48:17 +0000 (13:48 +0200)
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>
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c

index e1cb01a22fa8aa3048237bc93ebc9979c46c9394..a7189a3b4d70f759ab9743f8b43c4a2b83c1e47f 100644 (file)
@@ -85,6 +85,8 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
        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);
index cf0347f61b21c48e4a0507706121ec0b88ef7af5..08ce8177c3af154ae76ff7ed424d585ecde51984 100644 (file)
@@ -84,13 +84,15 @@ pgd_t * __init efi_call_phys_prolog(void)
 
        if (!efi_enabled(EFI_OLD_MEMMAP)) {
                efi_switch_mm(&efi_mm);
-               return NULL;
+               return efi_mm.pgd;
        }
 
        early_code_mapping_set_exec(1);
 
        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
@@ -138,10 +140,11 @@ pgd_t * __init efi_call_phys_prolog(void)
                pgd_offset_k(pgd * PGDIR_SIZE)->pgd &= ~_PAGE_NX;
        }
 
-out:
        __flush_tlb_all();
-
        return save_pgd;
+out:
+       efi_call_phys_epilog(save_pgd);
+       return NULL;
 }
 
 void __init efi_call_phys_epilog(pgd_t *save_pgd)