efi/x86: Don't panic or BUG() on non-critical error conditions
authorArd Biesheuvel <ardb@kernel.org>
Fri, 3 Jan 2020 11:39:46 +0000 (12:39 +0100)
committerIngo Molnar <mingo@kernel.org>
Fri, 10 Jan 2020 17:55:03 +0000 (18:55 +0100)
The logic in __efi_enter_virtual_mode() does a number of steps in
sequence, all of which may fail in one way or the other. In most
cases, we simply print an error and disable EFI runtime services
support, but in some cases, we BUG() or panic() and bring down the
system when encountering conditions that we could easily handle in
the same way.

While at it, replace a pointless page-to-virt-phys conversion with
one that goes straight from struct page to physical.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Matthew Garrett <mjg59@google.com>
Cc: linux-efi@vger.kernel.org
Link: https://lkml.kernel.org/r/20200103113953.9571-14-ardb@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c

index 53ed0b123641b4e4806f2eae1fcde22467291370..4f539bfdc051a781067b5a27b1d2329cfb3798ec 100644 (file)
@@ -889,16 +889,14 @@ static void __init __efi_enter_virtual_mode(void)
 
        if (efi_alloc_page_tables()) {
                pr_err("Failed to allocate EFI page tables\n");
-               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-               return;
+               goto err;
        }
 
        efi_merge_regions();
        new_memmap = efi_map_regions(&count, &pg_shift);
        if (!new_memmap) {
                pr_err("Error reallocating memory, EFI runtime non-functional!\n");
-               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-               return;
+               goto err;
        }
 
        pa = __pa(new_memmap);
@@ -912,8 +910,7 @@ static void __init __efi_enter_virtual_mode(void)
 
        if (efi_memmap_init_late(pa, efi.memmap.desc_size * count)) {
                pr_err("Failed to remap late EFI memory map\n");
-               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-               return;
+               goto err;
        }
 
        if (efi_enabled(EFI_DBG)) {
@@ -921,12 +918,11 @@ static void __init __efi_enter_virtual_mode(void)
                efi_print_memmap();
        }
 
-       BUG_ON(!efi.systab);
+       if (WARN_ON(!efi.systab))
+               goto err;
 
-       if (efi_setup_page_tables(pa, 1 << pg_shift)) {
-               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-               return;
-       }
+       if (efi_setup_page_tables(pa, 1 << pg_shift))
+               goto err;
 
        efi_sync_low_kernel_mappings();
 
@@ -935,9 +931,9 @@ static void __init __efi_enter_virtual_mode(void)
                                             efi.memmap.desc_version,
                                             (efi_memory_desc_t *)pa);
        if (status != EFI_SUCCESS) {
-               pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
-                        status);
-               panic("EFI call to SetVirtualAddressMap() failed!");
+               pr_err("Unable to switch EFI into virtual mode (status=%lx)!\n",
+                      status);
+               goto err;
        }
 
        efi_free_boot_services();
@@ -964,6 +960,10 @@ static void __init __efi_enter_virtual_mode(void)
 
        /* clean DUMMY object */
        efi_delete_dummy_variable();
+       return;
+
+err:
+       clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 }
 
 void __init efi_enter_virtual_mode(void)
index 910e9ec03b0924366ae4ae34e729da7d49ba970d..c13fa2150976a9f42e842b95a102635c16c0da20 100644 (file)
@@ -384,11 +384,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
                return 0;
 
        page = alloc_page(GFP_KERNEL|__GFP_DMA32);
-       if (!page)
-               panic("Unable to allocate EFI runtime stack < 4GB\n");
+       if (!page) {
+               pr_err("Unable to allocate EFI runtime stack < 4GB\n");
+               return 1;
+       }
 
-       efi_scratch.phys_stack = virt_to_phys(page_address(page));
-       efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
+       efi_scratch.phys_stack = page_to_phys(page + 1); /* stack grows down */
 
        npages = (_etext - _text) >> PAGE_SHIFT;
        text = __pa(_text);