Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1592471imm; Wed, 8 Aug 2018 21:33:14 -0700 (PDT) X-Google-Smtp-Source: AA+uWPwelL2mip44fNFmC1oyNK4i1P9Ye5l0KCePywJauzOCxf3sK/+Ooalr3ldlXhcMy9xDhs/0 X-Received: by 2002:a62:c8c2:: with SMTP id i63-v6mr599053pfk.73.1533789194621; Wed, 08 Aug 2018 21:33:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533789194; cv=none; d=google.com; s=arc-20160816; b=IX0vRNHIa7SEhdKlSxZIWGk5aQiySbzuDTl1ZNXL1Af3axMZjx/xTVgs7v/3pnQ4oF XgKQur3O0YL3YuiuTdWLqeKB7oyTvlKFFNYFrcmjuOgcI7oHsEdt9f1tDt2+e8GhFh7k E+AkquCxonkS7FWStEmd835tWDqdWYmj2W5i5zh09ZBvD+Y3qF/+NZe4v7eeftUz/60t asF3rTNCRKpjyfwXBCXG1ceFjSG7S4YmnHYDK3wWEK4+E4JkBCnOsYlqEa+4V7PBGQ6N cL4MJmHLUuDR0nPxWzAW+6Few5b6RXK1vlFe6u/qYbd4ICSkItymqo9cYgi9OZNf4oac d1gw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=u8l+Vd4Tw7Dd3/K42uqcTDLPj6wgIblGVAU9G810Z94=; b=DofMGBMwMlv2dZZClvlc5LQOPLZS0Sd7+eanL7Njnthf0HHb01u3kpJfhhy9sulk3S 1XShSvErgJsjOWv0FB3JUWGOLci050V5aO53A3pnIergSRnMSOCFXbAU02k8HgWM5bbo SzO9wrsEc5lOAnxBHyhJ9rQVMSdWPUpaVJdOukJOdsjuIbQuW3+GySzUXU+8c8zPB4lQ HpEp7sXeEcbD832MHDR0KlzAE8qs2TnCsllcrOdsHRZo/NpUp1DNeb5gozf5crAsa3zd fU61qwsq5J1G1pTapt+rHvgCu96vFlfl9EaygTsSaLLQQJuF9jPRcC7gICF0cETy4L0G fitA== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n24-v6si6316902pgb.665.2018.08.08.21.33.00; Wed, 08 Aug 2018 21:33:14 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728353AbeHIGyu (ORCPT + 99 others); Thu, 9 Aug 2018 02:54:50 -0400 Received: from mga11.intel.com ([192.55.52.93]:22077 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727211AbeHIGyu (ORCPT ); Thu, 9 Aug 2018 02:54:50 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 Aug 2018 21:31:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,213,1531810800"; d="scan'208";a="61024047" Received: from sai-dev-mach.sc.intel.com ([143.183.140.52]) by fmsmga007.fm.intel.com with ESMTP; 08 Aug 2018 21:31:59 -0700 From: Sai Praneeth Prakhya To: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ricardo.ner@intel.com, matt@codeblueprint.co.uk, Sai Praneeth , Lee Chun-Yi , Al Stone , Borislav Petkov , Ingo Molnar , Andy Lutomirski , Bhupesh Sharma , Peter Zijlstra , Ard Biesheuvel Subject: [PATCH V1 3/6] x86/efi: Permanently save the EFI_MEMORY_MAP passed by the firmware Date: Wed, 8 Aug 2018 21:31:14 -0700 Message-Id: <1533789077-16156-4-git-send-email-sai.praneeth.prakhya@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1533789077-16156-1-git-send-email-sai.praneeth.prakhya@intel.com> References: <1533789077-16156-1-git-send-email-sai.praneeth.prakhya@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sai Praneeth The efi page fault handler that fixes up page faults caused by the firmware needs the original memory map passed by the firmware. It looks up this memory map to find the type of the memory region at which the page fault occurred. Presently, EFI subsystem discards the original memory map passed by the firmware and replaces it with a new memory map that has only EFI_RUNTIME_SERVICES_ regions. But illegal accesses by firmware can occur at any region. Hence, _only_ if CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES is defined, create a backup of the original memory map passed by the firmware, so that efi page fault handler could detect/fix illegal accesses to *any* efi region. Suggested-by: Matt Fleming Based-on-code-from: Ricardo Neri Signed-off-by: Sai Praneeth Prakhya Cc: Lee Chun-Yi Cc: Al Stone Cc: Borislav Petkov Cc: Ingo Molnar Cc: Andy Lutomirski Cc: Bhupesh Sharma Cc: Peter Zijlstra Cc: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 6 ++++++ arch/x86/platform/efi/efi.c | 2 ++ arch/x86/platform/efi/quirks.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 9b70743400f3..c97f2e955cab 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -142,6 +142,12 @@ extern int __init efi_reuse_config(u64 tables, int nr_tables); extern void efi_delete_dummy_variable(void); extern void efi_switch_mm(struct mm_struct *mm); +#ifdef CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES +extern void __init efi_save_original_memmap(void); +#else +static inline void __init efi_save_original_memmap(void) { } +#endif /* CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES */ + struct efi_setup_data { u64 fw_vendor; u64 runtime; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 439c2c40bf03..7d18b7ed5d41 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -946,6 +946,8 @@ static void __init __efi_enter_virtual_mode(void) pa = __pa(new_memmap); + efi_save_original_memmap(); + /* * Unregister the early EFI memmap from efi_init() and install * the new EFI memory map that we are about to pass to the diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 844d31cb8a0c..84b213a1460a 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -654,3 +654,52 @@ int efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff, } #endif + +#ifdef CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES + +static bool original_memory_map_present; +static struct efi_memory_map original_memory_map; + +/* + * The page fault handler that fixes up page faults caused by buggy + * firmware needs original memory map (memory map passed by firmware). + * Hence, build a new EFI memmap that has *all* entries and save it for + * later use. + */ +void __init efi_save_original_memmap(void) +{ + efi_memory_desc_t *md; + void *remapped_phys, *new_md; + phys_addr_t new_phys, new_size; + + new_size = efi.memmap.desc_size * efi.memmap.nr_map; + new_phys = efi_memmap_alloc(efi.memmap.nr_map); + if (!new_phys) { + pr_err("Failed to allocate new EFI memmap\n"); + return; + } + + remapped_phys = memremap(new_phys, new_size, MEMREMAP_WB); + if (!remapped_phys) { + pr_err("Failed to remap new EFI memmap\n"); + __free_pages(pfn_to_page(PHYS_PFN(new_phys)), get_order(new_size)); + return; + } + + new_md = remapped_phys; + for_each_efi_memory_desc(md) { + memcpy(new_md, md, efi.memmap.desc_size); + new_md += efi.memmap.desc_size; + } + + original_memory_map.late = 1; + original_memory_map.phys_map = new_phys; + original_memory_map.map = remapped_phys; + original_memory_map.nr_map = efi.memmap.nr_map; + original_memory_map.desc_size = efi.memmap.desc_size; + original_memory_map.map_end = remapped_phys + new_size; + original_memory_map.desc_version = efi.memmap.desc_version; + + original_memory_map_present = true; +} +#endif /* CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES */ -- 2.7.4