]> xenbits.xensource.com Git - people/aperard/linux.git/commitdiff
arm64: efi: Limit allocations to 48-bit addressable physical region
authorArd Biesheuvel <ardb+git@google.com>
Mon, 4 Mar 2024 11:19:39 +0000 (12:19 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 Mar 2024 14:45:17 +0000 (14:45 +0000)
From: Ard Biesheuvel <ardb@kernel.org>

[ Commit a37dac5c5dcfe0f1fd58513c16cdbc280a47f628 upstream ]

The UEFI spec does not mention or reason about the configured size of
the virtual address space at all, but it does mention that all memory
should be identity mapped using a page size of 4 KiB.

This means that a LPA2 capable system that has any system memory outside
of the 48-bit addressable physical range and follows the spec to the
letter may serve page allocation requests from regions of memory that
the kernel cannot access unless it was built with LPA2 support and
enables it at runtime.

So let's ensure that all page allocations are limited to the 48-bit
range.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/efi.h
drivers/firmware/efi/libstub/alignedmem.c
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/mem.c
drivers/firmware/efi/libstub/randomalloc.c

index 62c846be2d76ac60894289e1afa2ef25c4f4e7c9..a75c0772ecfcae54944333dce301e2595177c99f 100644 (file)
@@ -103,6 +103,7 @@ static inline void free_screen_info(struct screen_info *si)
 }
 
 #define EFI_ALLOC_ALIGN                SZ_64K
+#define EFI_ALLOC_LIMIT                ((1UL << 48) - 1)
 
 /*
  * On ARM systems, virtually remapped UEFI runtime services are set up in two
index 174832661251e84611680592e9a7e4dc10de63f6..6b83c492c3b8260d52e16bb73a1d5abaa4cb943d 100644 (file)
@@ -29,6 +29,8 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
        efi_status_t status;
        int slack;
 
+       max = min(max, EFI_ALLOC_LIMIT);
+
        if (align < EFI_ALLOC_ALIGN)
                align = EFI_ALLOC_ALIGN;
 
index 08f46c072da56e4be336c2080ab034dc0386382d..40275c3131c8e3ef1778acb6e5cd5603b425eb72 100644 (file)
@@ -191,10 +191,11 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        if (status != EFI_SUCCESS) {
                if (!check_image_region((u64)_text, kernel_memsize)) {
                        efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
-               } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
+               } else if (IS_ALIGNED((u64)_text, min_kimg_align) &&
+                          (u64)_end < EFI_ALLOC_LIMIT) {
                        /*
                         * Just execute from wherever we were loaded by the
-                        * UEFI PE/COFF loader if the alignment is suitable.
+                        * UEFI PE/COFF loader if the placement is suitable.
                         */
                        *image_addr = (u64)_text;
                        *reserve_size = 0;
index ab505b07e626bdac405dc5456a1aba3a51e1fc19..002f02a6d3598e233875dec493ada3f4ce7c41c0 100644 (file)
 #define EFI_ALLOC_ALIGN                EFI_PAGE_SIZE
 #endif
 
+#ifndef EFI_ALLOC_LIMIT
+#define EFI_ALLOC_LIMIT                ULONG_MAX
+#endif
+
 extern bool efi_nochunk;
 extern bool efi_nokaslr;
 extern int efi_loglevel;
index 03d147f17185b329a54b4362bb7b2dae3e4565fc..4f1fa302234d880f68c4f63e92d3326c3cd4dd29 100644 (file)
@@ -89,6 +89,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
        efi_physical_addr_t alloc_addr;
        efi_status_t status;
 
+       max = min(max, EFI_ALLOC_LIMIT);
+
        if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
                return efi_allocate_pages_aligned(size, addr, max,
                                                  EFI_ALLOC_ALIGN,
index ec44bb7e092faf7d95a80319ec14639c0519e3fd..1692d19ae80f0065627650344aa6dbae92180928 100644 (file)
@@ -29,7 +29,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
                return 0;
 
        region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
-                        (u64)ULONG_MAX);
+                        (u64)EFI_ALLOC_LIMIT);
        if (region_end < size)
                return 0;