Re: [PATCH] x86/efi: Free allocated memory if remap fails
Hello Sai, On 16 June 2018 at 03:09, Sai Praneeth Prakhya wrote: > From: Sai Praneeth > > efi_memmap_alloc(), as the name suggests, allocates memory for a new efi > memory map. It's referenced from couple of places, namely, > efi_arch_mem_reserve() and efi_free_boot_services(). These callers, > after allocating memory, remap it for further use. As usual, a routine > check is performed to confirm successful remap. If the remap fails, > ideally, the allocated memory should be freed but presently we just > return without freeing it up. Hence, fix this bug by introducing > efi_memmap_free() which frees memory allocated by efi_memmap_alloc(). > > As efi_memmap_alloc() allocates memory depending on whether mm_init() > has already been invoked or not, similarly efi_memmap_free() frees > memory accordingly. > > efi_fake_memmap() also references efi_memmap_alloc() but it frees > memory correctly using memblock_free(), but replace it with > efi_memmap_free() to maintain consistency, as in, allocate memory with > efi_memmap_alloc() and free memory with efi_memmap_free(). > > It's a fact that memremap() and early_memremap() might never fail and > this code might never get a chance to run but to maintain good kernel > programming semantics, we might need this patch. > > Signed-off-by: Sai Praneeth Prakhya > Reviewed-by: Ricardo Neri Please don't include tags for reviews that did not happen on-list. > Cc: Lee Chun-Yi > Cc: Borislav Petkov > Cc: Tony Luck > Cc: Dave Hansen > Cc: Bhupesh Sharma > Cc: Ricardo Neri > Cc: Peter Zijlstra > Cc: Ravi Shankar > Cc: Matt Fleming > Cc: Ard Biesheuvel > --- > > I found this bug when working on a different patch set which uses > efi_memmap_alloc() and then noticed that I never freed the allocated > memory. I found it weird, in the sense that, memory is allocated but is > not freed (upon returning from an error). So, wasn't sure if that should > be treated as a bug or should I just leave it as is because everything > works fine even without this patch. Since the effort for the patch is > very minimal, I just went ahead and posted one, so that I could know > your thoughts on it. > > Note: Patch based on Linus's mainline tree V4.17 > > arch/x86/platform/efi/quirks.c | 10 ++ > drivers/firmware/efi/fake_mem.c | 2 +- > drivers/firmware/efi/memmap.c | 27 +++ > include/linux/efi.h | 1 + > 4 files changed, 35 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c > index 36c1f8b9f7e0..f223093f2df7 100644 > --- a/arch/x86/platform/efi/quirks.c > +++ b/arch/x86/platform/efi/quirks.c > @@ -285,6 +285,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 > size) > new = early_memremap(new_phys, new_size); > if (!new) { > pr_err("Failed to map new boot services memmap\n"); > + efi_memmap_free(new_phys, num_entries); > return; > } > > @@ -429,7 +430,7 @@ void __init efi_free_boot_services(void) > new = memremap(new_phys, new_size, MEMREMAP_WB); > if (!new) { > pr_err("Failed to map new EFI memmap\n"); > - return; > + goto free_mem; > } > > /* > @@ -450,10 +451,11 @@ void __init efi_free_boot_services(void) > > memunmap(new); > > - if (efi_memmap_install(new_phys, num_entries)) { > + if (efi_memmap_install(new_phys, num_entries)) > pr_err("Could not install new EFI memmap\n"); > - return; > - } > + > +free_mem: > + efi_memmap_free(new_phys, num_entries); Doesn't this free the memory map that you just installed? > } > > /* > diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c > index 6c7d60c239b5..63edcedee25b 100644 > --- a/drivers/firmware/efi/fake_mem.c > +++ b/drivers/firmware/efi/fake_mem.c > @@ -79,7 +79,7 @@ void __init efi_fake_memmap(void) > new_memmap = early_memremap(new_memmap_phy, > efi.memmap.desc_size * new_nr_map); > if (!new_memmap) { > - memblock_free(new_memmap_phy, efi.memmap.desc_size * > new_nr_map); > + efi_memmap_free(new_memmap_phy, new_nr_map); > return; > } > > diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c > index 5fc70520e04c..27d28cb4652d 100644 > --- a/drivers/firmware/efi/memmap.c > +++ b/drivers/firmware/efi/memmap.c > @@ -50,6 +50,33 @@ phys_addr_t __init efi_memmap_alloc(unsigned int > num_entries) > } > > /** > + * efi_memmap_free - Free memory allocated by efi_memmap_alloc() > + * @mem: Physical address allocated by efi_memmap_alloc() > + * @num_entries: Number of entries in the allocated map. > + * > + * efi_memmap_alloc() allocates memory depending on whether mm_init() > + * has already been invoked or not. It uses either memblock or "normal" > + * page
Re: [PATCH] x86/efi: Free allocated memory if remap fails
Hello Sai, On 16 June 2018 at 03:09, Sai Praneeth Prakhya wrote: > From: Sai Praneeth > > efi_memmap_alloc(), as the name suggests, allocates memory for a new efi > memory map. It's referenced from couple of places, namely, > efi_arch_mem_reserve() and efi_free_boot_services(). These callers, > after allocating memory, remap it for further use. As usual, a routine > check is performed to confirm successful remap. If the remap fails, > ideally, the allocated memory should be freed but presently we just > return without freeing it up. Hence, fix this bug by introducing > efi_memmap_free() which frees memory allocated by efi_memmap_alloc(). > > As efi_memmap_alloc() allocates memory depending on whether mm_init() > has already been invoked or not, similarly efi_memmap_free() frees > memory accordingly. > > efi_fake_memmap() also references efi_memmap_alloc() but it frees > memory correctly using memblock_free(), but replace it with > efi_memmap_free() to maintain consistency, as in, allocate memory with > efi_memmap_alloc() and free memory with efi_memmap_free(). > > It's a fact that memremap() and early_memremap() might never fail and > this code might never get a chance to run but to maintain good kernel > programming semantics, we might need this patch. > > Signed-off-by: Sai Praneeth Prakhya > Reviewed-by: Ricardo Neri Please don't include tags for reviews that did not happen on-list. > Cc: Lee Chun-Yi > Cc: Borislav Petkov > Cc: Tony Luck > Cc: Dave Hansen > Cc: Bhupesh Sharma > Cc: Ricardo Neri > Cc: Peter Zijlstra > Cc: Ravi Shankar > Cc: Matt Fleming > Cc: Ard Biesheuvel > --- > > I found this bug when working on a different patch set which uses > efi_memmap_alloc() and then noticed that I never freed the allocated > memory. I found it weird, in the sense that, memory is allocated but is > not freed (upon returning from an error). So, wasn't sure if that should > be treated as a bug or should I just leave it as is because everything > works fine even without this patch. Since the effort for the patch is > very minimal, I just went ahead and posted one, so that I could know > your thoughts on it. > > Note: Patch based on Linus's mainline tree V4.17 > > arch/x86/platform/efi/quirks.c | 10 ++ > drivers/firmware/efi/fake_mem.c | 2 +- > drivers/firmware/efi/memmap.c | 27 +++ > include/linux/efi.h | 1 + > 4 files changed, 35 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c > index 36c1f8b9f7e0..f223093f2df7 100644 > --- a/arch/x86/platform/efi/quirks.c > +++ b/arch/x86/platform/efi/quirks.c > @@ -285,6 +285,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 > size) > new = early_memremap(new_phys, new_size); > if (!new) { > pr_err("Failed to map new boot services memmap\n"); > + efi_memmap_free(new_phys, num_entries); > return; > } > > @@ -429,7 +430,7 @@ void __init efi_free_boot_services(void) > new = memremap(new_phys, new_size, MEMREMAP_WB); > if (!new) { > pr_err("Failed to map new EFI memmap\n"); > - return; > + goto free_mem; > } > > /* > @@ -450,10 +451,11 @@ void __init efi_free_boot_services(void) > > memunmap(new); > > - if (efi_memmap_install(new_phys, num_entries)) { > + if (efi_memmap_install(new_phys, num_entries)) > pr_err("Could not install new EFI memmap\n"); > - return; > - } > + > +free_mem: > + efi_memmap_free(new_phys, num_entries); Doesn't this free the memory map that you just installed? > } > > /* > diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c > index 6c7d60c239b5..63edcedee25b 100644 > --- a/drivers/firmware/efi/fake_mem.c > +++ b/drivers/firmware/efi/fake_mem.c > @@ -79,7 +79,7 @@ void __init efi_fake_memmap(void) > new_memmap = early_memremap(new_memmap_phy, > efi.memmap.desc_size * new_nr_map); > if (!new_memmap) { > - memblock_free(new_memmap_phy, efi.memmap.desc_size * > new_nr_map); > + efi_memmap_free(new_memmap_phy, new_nr_map); > return; > } > > diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c > index 5fc70520e04c..27d28cb4652d 100644 > --- a/drivers/firmware/efi/memmap.c > +++ b/drivers/firmware/efi/memmap.c > @@ -50,6 +50,33 @@ phys_addr_t __init efi_memmap_alloc(unsigned int > num_entries) > } > > /** > + * efi_memmap_free - Free memory allocated by efi_memmap_alloc() > + * @mem: Physical address allocated by efi_memmap_alloc() > + * @num_entries: Number of entries in the allocated map. > + * > + * efi_memmap_alloc() allocates memory depending on whether mm_init() > + * has already been invoked or not. It uses either memblock or "normal" > + * page