x86/efi: defer freeing of boot services memory
Subsystems (4)
PATCH v2 1/1 x86/efi: defer freeing of boot services memory
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services() frees memory occupied by EFI_BOOT_SERVICES_CODE and EFI_BOOT_SERVICES_DATA using memblock_free_late().
There are two issue with that: memblock_free_late() should be used for memory allocated with memblock_alloc() while the memory reserved with memblock_reserve() should be freed with free_reserved_area().
More acutely, with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y efi_free_boot_services() is called before deferred initialization of the memory map is complete.
Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
If the freed memory resides in the areas that memory map for them is still uninitialized, they won't be actually freed because memblock_free_late() calls memblock_free_pages() and the latter skips uninitialized pages.
Using free_reserved_area() at this point is also problematic because __free_page() accesses the buddy of the freed page and that again might end up in uninitialized part of the memory map.
Delaying the entire efi_free_boot_services() could be problematic because in addition to freeing boot services memory it updates efi.memmap without any synchronization and that's undesirable late in boot when there is concurrency.
More robust approach is to only defer freeing of the EFI boot services memory.
Split efi_free_boot_services() in two. First efi_unmap_boot_services() collects ranges that should be freed into an array then efi_free_boot_services() later frees them after deferred init is complete.
---
v1: https://lore.kernel.org/all/[email protected]
* update the commit message with correct function names (Ben)
arch/x86/include/asm/efi.h | 2 +- arch/x86/platform/efi/efi.c | 2 +- arch/x86/platform/efi/quirks.c | 55 +++++++++++++++++++++++++++-- drivers/firmware/efi/mokvar-table.c | 2 +- 4 files changed, 55 insertions(+), 6 deletions(-)
arch/x86/include/asm/efi.h +1 -1
@@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quirks(void);extern int __init efi_reuse_config (u64 tables,int nr_tables);extern void efi_delete_dummy_variable (void );extern void efi_crash_gracefully_on_page_fault (unsigned long phys_addr); -extern void efi_free_boot_services (void ); +extern void efi_unmap_boot_services (void );void arch_efi_call_virt_setup (void );void arch_efi_call_virt_teardown (void );
arch/x86/platform/efi/efi.c +1 -1
@@ -836,7 +836,7 @@ static void __init __efi_enter_virtual_mode(void) }efi_check_for_embedded_firmwares (); -efi_free_boot_services (); +efi_unmap_boot_services ();if (!efi_is_mixed ())efi_native_runtime_setup ();
arch/x86/platform/efi/quirks.c +52 -3
89 lines not on this page · raw message
drivers/firmware/efi/mokvar-table.c +1 -1
@@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj;* as an alternative to ordinary EFI variables, due to platform-dependent * limitations. The memory occupied by this table is marked as reserved. * -* This routine must be called before efi_free_boot_services() in order +* This routine must be called before efi_unmap_boot_services() in order * to guarantee that it can mark the table as reserved. * * Implicit inputs:
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
Signature · 1 line
2.51.0
Gentle ping?
Quoted 194 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services()frees memory occupied byEFI_BOOT_SERVICES_CODEandEFI_BOOT_SERVICES_DATAusingmemblock_free_late().There are two issue with that:
memblock_free_late()should be used for memory allocated withmemblock_alloc()while the memory reserved withmemblock_reserve()should be freed withfree_reserved_area().More acutely, with
CONFIG_DEFERRED_STRUCT_PAGE_INIT=yefi_free_boot_services()is called before deferred initialization of the memory map is complete.Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
If the freed memory resides in the areas that memory map for them is still uninitialized, they won't be actually freed because
memblock_free_late()callsmemblock_free_pages()and the latter skips uninitialized pages.Using
free_reserved_area()at this point is also problematic because__free_page()accesses the buddy of the freed page and that again might end up in uninitialized part of the memory map.Delaying the entire
efi_free_boot_services()could be problematic because in addition to freeing boot services memory it updates efi.memmap without any synchronization and that's undesirable late in boot when there is concurrency.More robust approach is to only defer freeing of the EFI boot services memory.
Split
efi_free_boot_services()in two. Firstefi_unmap_boot_services()collects ranges that should be freed into an array thenefi_free_boot_services()later frees them after deferred init is complete.Link https://lore.kernel.org/all/ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org open hereFixes 916f676f8dc0 ("x86, efi: Retain boot service code until after switching to virtual mode")Cc <[email protected]>Signed-off-by Mike Rapoport (Microsoft) <[email protected]>Reviewed-by Benjamin Herrenschmidt <[email protected]>---
v1: https://lore.kernel.org/all/[email protected]
* update the commit message with correct function names (Ben)arch/x86/include/asm/efi.h | 2 +- arch/x86/platform/efi/efi.c | 2 +- arch/x86/platform/efi/quirks.c | 55 +++++++++++++++++++++++++++-- drivers/firmware/efi/mokvar-table.c | 2 +- 4 files changed, 55 insertions(+), 6 deletions(-)arch/x86/include/asm/efi.h +1
-1@@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quirks(void);extern int __init efi_reuse_config (u64 tables,int nr_tables);extern void efi_delete_dummy_variable (void );extern void efi_crash_gracefully_on_page_fault (unsigned long phys_addr); -extern void efi_free_boot_services (void ); +extern void efi_unmap_boot_services (void );void arch_efi_call_virt_setup (void );void arch_efi_call_virt_teardown (void );arch/x86/platform/efi/efi.c +1
-1@@ -836,7 +836,7 @@ static void __init __efi_enter_virtual_mode(void) }efi_check_for_embedded_firmwares (); -efi_free_boot_services (); +efi_unmap_boot_services ();if (!efi_is_mixed ())efi_native_runtime_setup ();arch/x86/platform/efi/quirks.c +52
-3@@ -341,7 +341,7 @@ void __init efi_reserve_boot_services(void)/* * Because the following memblock_reserve() is paired -* with memblock_free_late() for this region in +* with free_reserved_area() for this region in * efi_free_boot_services(), we must be extremely * careful not to reserve, and subsequently free, * critical regions of memory (like the kernel image) or @@ -404,17 +404,33 @@ static void __init efi_unmap_pages(efi_memory_desc_t *md)pr_err ("Failed to unmap VA mapping for 0x%llx\n" , va); } -void __init efi_free_boot_services (void ) +struct efi_freeable_range { +u64 start; +u64 end; +}; + +static struct efi_freeable_range *ranges_to_free; + +void __init efi_unmap_boot_services (void ) {struct efi_memory_map_data data = {0 };efi_memory_desc_t *md;int num_entries =0 ; +int idx =0 ; +size_t sz;void *new, *new_md;/* Keep all regions for /sys/kernel/debug/efi */ if (efi_enabled (EFI_DBG ))return ; + sz =sizeof (*ranges_to_free) * efi.memmap.nr_map +1 ; + ranges_to_free =kzalloc (sz,GFP_KERNEL ); +if (!ranges_to_free) { +pr_err ("Failed to allocate storage for freeable EFI regions\n" ); +return ; + } +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;@@ -471,7 +487,15 @@ void __init efi_free_boot_services(void) start =SZ_1M ; } -memblock_free_late (start, size); +/* +* With CONFIG_DEFERRED_STRUCT_PAGE_INIT parts of the memory +* map are still not initialized and we can't reliably free +* memory here. +* Queue the ranges to free at a later point. +*/ + ranges_to_free[idx].start = start; + ranges_to_free[idx].end = start + size; + idx++; }if (!num_entries)@@ -512,6 +536,31 @@ void __init efi_free_boot_services(void) } } +static int __init efi_free_boot_services (void ) +{ +struct efi_freeable_range *range = ranges_to_free; +unsigned long freed =0 ; + +if (!ranges_to_free) +return 0 ; + +while (range->start) { +void *start =phys_to_virt (range->start); +void *end =phys_to_virt (range->end); + +free_reserved_area (start, end,-1 ,NULL ); + freed += (end - start); + range++; + } +kfree (ranges_to_free); + +if (freed) +pr_info ("Freeing EFI boot services memory: %ldK\n" , freed /SZ_1K ); + +return 0 ; +} +arch_initcall (efi_free_boot_services); +/* * A number of config table entries get remapped to virtual addresses * after entering EFI virtual mode. However, the kexec kernel requires drivers/firmware/efi/mokvar-table.c +1
-1@@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj;* as an alternative to ordinary EFI variables, due to platform-dependent * limitations. The memory occupied by this table is marked as reserved. * -* This routine must be called before efi_free_boot_services() in order +* This routine must be called before efi_unmap_boot_services() in order * to guarantee that it can mark the table as reserved. * * Implicit inputs: base-commit:
6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27fSignature · 1 line
2.51.0
Signature · 2 lines
Sincerely yours, Mike.
Quoted 1 line · Mike Rapoport
Gentle ping?
Ard, I _think_ this is one of the efi things in arch/x86 that you normally wrangle. Are you planning to grab this?
Ard Biesheuvel
maintainerQuoted 5 lines · Dave Hansen
Quoted 1 line · Mike Rapoport
Gentle ping?
Ard, I _think_ this is one of the efi things in
arch/x86that you normally wrangle. Are you planning to grab this?
Yes, I will pick it up. I'm planning some cleanup on top, but those will not be fixes anyway so this should go in on its own merit.
Ard Biesheuvel
maintainerQuoted 9 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services()frees memory occupied byEFI_BOOT_SERVICES_CODEandEFI_BOOT_SERVICES_DATAusingmemblock_free_late().There are two issue with that:
memblock_free_late()should be used for memory allocated withmemblock_alloc()while the memory reserved withmemblock_reserve()should be freed withfree_reserved_area().
Quoted 7 lines
More acutely, with
CONFIG_DEFERRED_STRUCT_PAGE_INIT=yefi_free_boot_services()is called before deferred initialization of the memory map is complete.Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
Putting a fixes tag referencing a patch that dates back to 2011 doesn't seem that useful here. Is this really an issue that goes all the way back? Or did a later change trigger the actual leak?
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services()frees memory occupied byEFI_BOOT_SERVICES_CODEandEFI_BOOT_SERVICES_DATAusingmemblock_free_late().There are two issue with that:
memblock_free_late()should be used for memory allocated withmemblock_alloc()while the memory reserved withmemblock_reserve()should be freed withfree_reserved_area().More acutely, with
CONFIG_DEFERRED_STRUCT_PAGE_INIT=yefi_free_boot_services()is called before deferred initialization of the memory map is complete.
Quoted 7 lines
Quoted 3 lines
Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
Putting a fixes tag referencing a patch that dates back to 2011 doesn't seem that useful here. Is this really an issue that goes all the way back? Or did a later change trigger the actual leak?
You are right, the leak was triggered later by addition of deferred initialization of struct pages which is about 4.2 time.
So fixes tag is wrong indeed, but all the currently maintained stable versions are affected.
Signature · 2 lines
Sincerely yours, Mike.
Ard Biesheuvel
maintainerQuoted 24 lines · Mike Rapoport
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services()frees memory occupied byEFI_BOOT_SERVICES_CODEandEFI_BOOT_SERVICES_DATAusingmemblock_free_late().There are two issue with that:
memblock_free_late()should be used for memory allocated withmemblock_alloc()while the memory reserved withmemblock_reserve()should be freed withfree_reserved_area().More acutely, with
CONFIG_DEFERRED_STRUCT_PAGE_INIT=yefi_free_boot_services()is called before deferred initialization of the memory map is complete.Quoted 7 lines
Quoted 3 lines
Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
Putting a fixes tag referencing a patch that dates back to 2011 doesn't seem that useful here. Is this really an issue that goes all the way back? Or did a later change trigger the actual leak?
Quoted 6 lines
You are right, the leak was triggered later by addition of deferred initialization of struct pages which is about 4.2 time.
So fixes tag is wrong indeed, but all the currently maintained stable versions are affected.
Fair enough. It's already in -next so I will just leave it as is.
Hi,
Quoted 108 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
efi_free_boot_services()frees memory occupied byEFI_BOOT_SERVICES_CODEandEFI_BOOT_SERVICES_DATAusingmemblock_free_late().There are two issue with that:
memblock_free_late()should be used for memory allocated withmemblock_alloc()while the memory reserved withmemblock_reserve()should be freed withfree_reserved_area().More acutely, with
CONFIG_DEFERRED_STRUCT_PAGE_INIT=yefi_free_boot_services()is called before deferred initialization of the memory map is complete.Benjamin Herrenschmidt reports that this causes a leak of ~140MB of RAM on EC2 t3a.nano instances which only have 512MB or RAM.
If the freed memory resides in the areas that memory map for them is still uninitialized, they won't be actually freed because
memblock_free_late()callsmemblock_free_pages()and the latter skips uninitialized pages.Using
free_reserved_area()at this point is also problematic because__free_page()accesses the buddy of the freed page and that again might end up in uninitialized part of the memory map.Delaying the entire
efi_free_boot_services()could be problematic because in addition to freeing boot services memory it updates efi.memmap without any synchronization and that's undesirable late in boot when there is concurrency.More robust approach is to only defer freeing of the EFI boot services memory.
Split
efi_free_boot_services()in two. Firstefi_unmap_boot_services()collects ranges that should be freed into an array thenefi_free_boot_services()later frees them after deferred init is complete.Link https://lore.kernel.org/all/ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org open hereFixes 916f676f8dc0 ("x86, efi: Retain boot service code until after switching to virtual mode")Cc <[email protected]>Signed-off-by Mike Rapoport (Microsoft) <[email protected]>Reviewed-by Benjamin Herrenschmidt <[email protected]>---
v1: https://lore.kernel.org/all/[email protected]
* update the commit message with correct function names (Ben)arch/x86/include/asm/efi.h | 2 +- arch/x86/platform/efi/efi.c | 2 +- arch/x86/platform/efi/quirks.c | 55 +++++++++++++++++++++++++++-- drivers/firmware/efi/mokvar-table.c | 2 +- 4 files changed, 55 insertions(+), 6 deletions(-)arch/x86/include/asm/efi.h +1
-1@@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quirks(void);extern int __init efi_reuse_config (u64 tables,int nr_tables);extern void efi_delete_dummy_variable (void );extern void efi_crash_gracefully_on_page_fault (unsigned long phys_addr); -extern void efi_free_boot_services (void ); +extern void efi_unmap_boot_services (void );void arch_efi_call_virt_setup (void );void arch_efi_call_virt_teardown (void );arch/x86/platform/efi/efi.c +1
-1@@ -836,7 +836,7 @@ static void __init __efi_enter_virtual_mode(void) }efi_check_for_embedded_firmwares (); -efi_free_boot_services (); +efi_unmap_boot_services ();if (!efi_is_mixed ())efi_native_runtime_setup ();arch/x86/platform/efi/quirks.c +9
-2@@ -341,7 +341,7 @@ void __init efi_reserve_boot_services(void)/* * Because the following memblock_reserve() is paired -* with memblock_free_late() for this region in +* with free_reserved_area() for this region in * efi_free_boot_services(), we must be extremely * careful not to reserve, and subsequently free, * critical regions of memory (like the kernel image) or @@ -404,17 +404,33 @@ static void __init efi_unmap_pages(efi_memory_desc_t *md)pr_err ("Failed to unmap VA mapping for 0x%llx\n" , va); } -void __init efi_free_boot_services (void ) +struct efi_freeable_range { +u64 start; +u64 end; +}; + +static struct efi_freeable_range *ranges_to_free; + +void __init efi_unmap_boot_services (void ) {struct efi_memory_map_data data = {0 };efi_memory_desc_t *md;
arch/x86/platform/efi/quirks.c static void __init efi_unmap_pages(efi_memory_desc_t *md) · line 427
Quoted 10 lines
arch/x86/platform/efi/quirks.c +3
-0int num_entries =0 ; +int idx =0 ; +size_t sz;void *new, *new_md;/* Keep all regions for /sys/kernel/debug/efi */ if (efi_enabled (EFI_DBG ))return ; + sz =sizeof (*ranges_to_free) * efi.memmap.nr_map +1 ;
Was this possibly supposed to be
sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1); ^ ^
?
Thanks,
Guenter
Quoted 75 lines
arch/x86/platform/efi/quirks.c +40
-1+ ranges_to_free =kzalloc (sz,GFP_KERNEL ); +if (!ranges_to_free) { +pr_err ("Failed to allocate storage for freeable EFI regions\n" ); +return ; + } +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;@@ -471,7 +487,15 @@ void __init efi_free_boot_services(void) start =SZ_1M ; } -memblock_free_late (start, size); +/* +* With CONFIG_DEFERRED_STRUCT_PAGE_INIT parts of the memory +* map are still not initialized and we can't reliably free +* memory here. +* Queue the ranges to free at a later point. +*/ + ranges_to_free[idx].start = start; + ranges_to_free[idx].end = start + size; + idx++; }if (!num_entries)@@ -512,6 +536,31 @@ void __init efi_free_boot_services(void) } } +static int __init efi_free_boot_services (void ) +{ +struct efi_freeable_range *range = ranges_to_free; +unsigned long freed =0 ; + +if (!ranges_to_free) +return 0 ; + +while (range->start) { +void *start =phys_to_virt (range->start); +void *end =phys_to_virt (range->end); + +free_reserved_area (start, end,-1 ,NULL ); + freed += (end - start); + range++; + } +kfree (ranges_to_free); + +if (freed) +pr_info ("Freeing EFI boot services memory: %ldK\n" , freed /SZ_1K ); + +return 0 ; +} +arch_initcall (efi_free_boot_services); +/* * A number of config table entries get remapped to virtual addresses * after entering EFI virtual mode. However, the kexec kernel requires drivers/firmware/efi/mokvar-table.c +1
-1@@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj;* as an alternative to ordinary EFI variables, due to platform-dependent * limitations. The memory occupied by this table is marked as reserved. * -* This routine must be called before efi_free_boot_services() in order +* This routine must be called before efi_unmap_boot_services() in order * to guarantee that it can mark the table as reserved. * * Implicit inputs: base-commit:
6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27fSignature · 1 line
2.51.
Quoted 15 lines · Guenter Roeck
Hi,
Quoted 13 lines
(quoted diff) +3
-0+void __init efi_unmap_boot_services(void) { struct efi_memory_map_data data = { 0 }; efi_memory_desc_t *md; int num_entries = 0; + int idx = 0; + size_t sz; void *new, *new_md; /* Keep all regions for /sys/kernel/debug/efi */ if (efi_enabled(EFI_DBG)) return;
Quoted 6 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;Was this possibly supposed to be
sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1); ^ ^?
Yes, thanks for catching this.
@Ard, can you please pick the fix:
From 8fc5c5e828e7d127e6210bc9952451300591cdce Mon Sep 17 00:00:00 2001
From: "Mike Rapoport (Microsoft)" <[email protected]>
Date: Fri, 20 Mar 2026 15:59:48 +0200
Subject: [PATCH] x86/efi: efi_unmap_boot_services: fix calculation of
ranges_to_free size
ranges_to_free array should have enough room to store the entire EFI memmap plus an extra element for NULL entry.
The calculation of this array size wrongly adds 1 to the overall size instead of adding 1 to the number of elements.
Add parentheses to properly size the array.
--- arch/x86/platform/efi/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/platform/efi/quirks.c +1 -1
@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)if (efi_enabled (EFI_DBG ))return ; - sz =sizeof (*ranges_to_free) * efi.memmap.nr_map +1 ; + sz =sizeof (*ranges_to_free) * (efi.memmap.nr_map +1 ); ranges_to_free =kzalloc (sz,GFP_KERNEL );if (!ranges_to_free) {pr_err ("Failed to allocate storage for freeable EFI regions\n" );
Signature · 1 line
2.53.0
Ard Biesheuvel
maintainerQuoted 23 lines · Mike Rapoport
Quoted 15 lines · Guenter Roeck
Hi,
Quoted 13 lines
(quoted diff) +3
-0+void __init efi_unmap_boot_services(void) { struct efi_memory_map_data data = { 0 }; efi_memory_desc_t *md; int num_entries = 0; + int idx = 0; + size_t sz; void *new, *new_md; /* Keep all regions for /sys/kernel/debug/efi */ if (efi_enabled(EFI_DBG)) return;Quoted 6 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;Was this possibly supposed to be
sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1); ^ ^?
Quoted 4 lines
Yes, thanks for catching this.
@Ard, can you please pick the fix:
Yep, queued up now.
Thanks for the fix.
Quoted 33 lines
From
8fc5c5e828e7d127e6210bc9952451300591cdceMon Sep 17 00:00:00 2001
From: "Mike Rapoport (Microsoft)" <[email protected]>
Date: Fri, 20 Mar 2026 15:59:48 +0200
Subject: [PATCH] x86/efi:efi_unmap_boot_services: fix calculation of
ranges_to_freesize
ranges_to_freearray should have enough room to store the entire EFI memmap plus an extra element for NULL entry.
The calculation of this array size wrongly adds 1 to the overall size instead of adding 1 to the number of elements.Add parentheses to properly size the array.
Reported-by Guenter Roeck <[email protected]>Fixes a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")Signed-off-by Mike Rapoport (Microsoft) <[email protected]>--- arch/x86/platform/efi/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/x86/platform/efi/quirks.c +1
-1@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)if (efi_enabled (EFI_DBG ))return ; - sz =sizeof (*ranges_to_free) * efi.memmap.nr_map +1 ; + sz =sizeof (*ranges_to_free) * (efi.memmap.nr_map +1 ); ranges_to_free =kzalloc (sz,GFP_KERNEL );if (!ranges_to_free) {pr_err ("Failed to allocate storage for freeable EFI regions\n" );
Quoted 16 lines · Mike Rapoport
Quoted 15 lines · Guenter Roeck
Hi,
Quoted 13 lines
(quoted diff) +3
-0+void __init efi_unmap_boot_services(void) { struct efi_memory_map_data data = { 0 }; efi_memory_desc_t *md; int num_entries = 0; + int idx = 0; + size_t sz; void *new, *new_md; /* Keep all regions for /sys/kernel/debug/efi */ if (efi_enabled(EFI_DBG)) return;
Quoted 9 lines
Quoted 6 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;Was this possibly supposed to be
sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1); ^ ^?
Yes, thanks for catching this.
Thanks for confirming.
Just for the record, it wasn't really me, it was an instance of Sashiko running on the LTS backport of the patch.
Guenter
Quoted 35 lines
@Ard, can you please pick the fix:
From
8fc5c5e828e7d127e6210bc9952451300591cdceMon Sep 17 00:00:00 2001
From: "Mike Rapoport (Microsoft)" <[email protected]>
Date: Fri, 20 Mar 2026 15:59:48 +0200
Subject: [PATCH] x86/efi:efi_unmap_boot_services: fix calculation of
ranges_to_freesize
ranges_to_freearray should have enough room to store the entire EFI memmap plus an extra element for NULL entry.
The calculation of this array size wrongly adds 1 to the overall size instead of adding 1 to the number of elements.Add parentheses to properly size the array.
Reported-by Guenter Roeck <[email protected]>Fixes a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")Signed-off-by Mike Rapoport (Microsoft) <[email protected]>--- arch/x86/platform/efi/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/x86/platform/efi/quirks.c +1
-1@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)if (efi_enabled (EFI_DBG ))return ; - sz =sizeof (*ranges_to_free) * efi.memmap.nr_map +1 ; + sz =sizeof (*ranges_to_free) * (efi.memmap.nr_map +1 ); ranges_to_free =kzalloc (sz,GFP_KERNEL );if (!ranges_to_free) {pr_err ("Failed to allocate storage for freeable EFI regions\n" );