Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3722241imm; Mon, 18 Jun 2018 03:00:10 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKawQp8tGWMtOjJ6+kHDX+QRy3gaV+DCeDDUAfjL9B27/NC1wWPrY46UBo7uLrs+TldV6fz X-Received: by 2002:a65:4146:: with SMTP id x6-v6mr10475311pgp.221.1529316010108; Mon, 18 Jun 2018 03:00:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529316010; cv=none; d=google.com; s=arc-20160816; b=fOM+Lb5rRhtkkFkCEgIV6+goWmElWplxO3OawASRm8+Cn4j8fdIf1FfWlH9sfCZnmJ ilzaZ29eDeMWoRvUm666phuGQ9/5/4RfpuA4RQLmGNV1V/9rNCq+eb+aauRzUGaIg263 eSa9OX/xxbfqfUwFibBRIgkszsYMDQHuWl5qzmgTmsFsCxhZ0xnAEKqjHO4BNiG3BXKf +9j7fnPobtOAybDM2/VNkPqJkb4ii3eTuK0ImcYd6R80S1cPexCDhTLYRBKWoy4UTsww mIm2Y2TpQol5pfOc3LxqxdLAmAuLvSDYaoLVfodXfi65SXK3Qru1pBGFPhHxG///ZmlS y0bQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=LQ5aSUsVekwjiVc4S9ah6C2vtGPKqPb+94NXMEbp/YQ=; b=kATRqQFbFSZoUJSf56bxK4W9RUUBE6NGqpVewnBYR1I+ClICv9yjPiM1IP3mP4z08a B+xuwrn6HjjSZz2IU/ekzwAeu01DVFbSqynCcCFo6IkC7oUO5YLW1ihcsxMcym6Gqgap RrqAljL9SzTSeAckBX9M4D4Uw0AIgS83GlFVOTq+iJuL3ZKsnJBRaVC5ixAC8CiZ4RXY usxb2Bm4FVWj/20yb3dHARd//oAslyOK+lnPJRKUWGANToOUl0XO+WTUnZWW934YEc4W PUaDZgV1hVVYfAVwwSXaHv5byeccP+MVLg3iy4QYqma3GIMAeeIwrNfVCcO0z7KeiXpE IjSA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EEgCjyIa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p11-v6si14492189plq.33.2018.06.18.02.59.56; Mon, 18 Jun 2018 03:00:10 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EEgCjyIa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965197AbeFRJ6D (ORCPT + 99 others); Mon, 18 Jun 2018 05:58:03 -0400 Received: from mail-it0-f65.google.com ([209.85.214.65]:36116 "EHLO mail-it0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935651AbeFRJ6A (ORCPT ); Mon, 18 Jun 2018 05:58:00 -0400 Received: by mail-it0-f65.google.com with SMTP id j135-v6so11143992itj.1 for ; Mon, 18 Jun 2018 02:58:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=LQ5aSUsVekwjiVc4S9ah6C2vtGPKqPb+94NXMEbp/YQ=; b=EEgCjyIaCrzKAxiRDc94Mpm6EZPKPdb33keqY9+Grjc5XNP0iEpv9BlOWGggMNSDK7 K5xJt/8YlCPnfUZTlncXsVw+sDHAsKACy64aUoWLX+91pPkvkBD4ZSTxOZhXZKavXCXs nd8rZYMH749p9/0DBSke6Hc8xH0qSZBvJnpVA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=LQ5aSUsVekwjiVc4S9ah6C2vtGPKqPb+94NXMEbp/YQ=; b=rLZT32c7/cv8je8XYMMfIZnY1pKnT8EUMsroDHsknuPu4tcLGLCNnX6er7hUJMOtVE +TYwIY7gkrwDpNpSPmyTxs19We1uXGkjb9di/ZsToCmFS8b8++b4A3uLGxm4kwNzzTw3 n6tnNdn5NhUvFvGpyjfOquuYZXOVOU6Cnev1Yr4PmHclmbAaacKNmP5lM3590XSFS4Ti vCg1Q3ESOJ7GJ8FLbvjWwMN7A2xNbV/mGrFkI6hSYx8lLhZ9k7G4eiWw7g3K5WACUBF7 pP2cntE6KrWC2/ZyHaHOiSt1ia2Z9Z3EUo7vWnj8x23y75sJZl48aYmH7UNlfSY9mTOh Ie+g== X-Gm-Message-State: APt69E28XGNpwwwfyyFN+g48Zo0ok3hwAKgSUjLB/l0GiXF8BruwktTy FHPx1a7q6ymE1K58iYaBmtzQNxedkskD61+l6PtKkQ== X-Received: by 2002:a02:4187:: with SMTP id n7-v6mr9389258jad.86.1529315879788; Mon, 18 Jun 2018 02:57:59 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a6b:bbc7:0:0:0:0:0 with HTTP; Mon, 18 Jun 2018 02:57:59 -0700 (PDT) In-Reply-To: <1529111365-32295-1-git-send-email-sai.praneeth.prakhya@intel.com> References: <1529111365-32295-1-git-send-email-sai.praneeth.prakhya@intel.com> From: Ard Biesheuvel Date: Mon, 18 Jun 2018 11:57:59 +0200 Message-ID: Subject: Re: [PATCH] x86/efi: Free allocated memory if remap fails To: Sai Praneeth Prakhya Cc: linux-efi , Linux Kernel Mailing List , Lee Chun-Yi , Borislav Petkov , Tony Luck , Dave Hansen , Bhupesh Sharma , Ricardo Neri , Peter Zijlstra , Ravi Shankar , Matt Fleming Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 allocation. Use this function to free the memory allocated by > + * efi_memmap_alloc(). Since the allocation is done in two different > + * ways, similarly, we free it in two different ways. > + * > + */ > +void __init efi_memmap_free(phys_addr_t mem, unsigned int num_entries) > +{ > + unsigned long size = num_entries * efi.memmap.desc_size; > + unsigned int order = get_order(size); > + phys_addr_t end = mem + size - 1; > + > + if (slab_is_available()) { > + __free_pages(pfn_to_page(PHYS_PFN(mem)), order); How do you know that the memory you are freeing was allocated when slab_is_available() was already true? > + return; > + } > + > + if (memblock_free(mem, size)) > + pr_err("Failed to free mem from %pa to %pa\n", &mem, &end); > +} > + > +/** > * __efi_memmap_init - Common code for mapping the EFI memory map > * @data: EFI memory map data > * @late: Use early or late mapping function? > diff --git a/include/linux/efi.h b/include/linux/efi.h > index 3016d8c456bc..f5d1cf44b320 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -1016,6 +1016,7 @@ extern int __init efi_memmap_split_count(efi_memory_desc_t *md, > struct range *range); > extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap, > void *buf, struct efi_mem_range *mem); > +void __init efi_memmap_free(phys_addr_t mem, unsigned int num_entries); > > extern int efi_config_init(efi_config_table_type_t *arch_tables); > #ifdef CONFIG_EFI_ESRT > -- > 2.7.4 >