Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp895488imm; Sun, 2 Sep 2018 02:50:17 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZPzpUGCghnC+pjxHej6O03gaFam4GV57vw0kxvxvtLNhcfZFY6QFYUV2OkZQjhZpdUcGIw X-Received: by 2002:a63:1d3:: with SMTP id 202-v6mr21621838pgb.136.1535881817675; Sun, 02 Sep 2018 02:50:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535881817; cv=none; d=google.com; s=arc-20160816; b=xnjExQIm2/tPn32Ibbq4W7PnCed7Ph8d6tHuHLYYBDdGbh/a60FG33YqdJzeyeZyJQ Rwi3WloTrmmxfjjCEVr/9UNs4OIlALcBXaFgRDdKwC9KjwFnCaoJDNdgVKqU96DMEg80 kHS57WNMDao35wWz14SzbYgyYzOOXyraivFxjwja10hW4hb0N7Iw1h6QjCHzpAv794yH wOJjj198cJmlyOsEgWxMFGUuCzetjt1HzhKZCFW+sMwxCpBP8GeJd2o7g0FVwolC4llT mUi41v1W97rqlu2ORstRGrLf3qo4je7i6fNEvCSEVMLOpF5eqpuy4o3QArbEqmcwY2Cx Nnxg== 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=odhiXMDO4Sb8yKHc72N7S5DgYLPL+ynTdlqYwN8nC24=; b=fHj3ShZ/0MZ6JlR3EBYZ9gdjbcrPTslWrHRv+89z1SUnBeZh05rr7T15YFTAWq33mL +xTCQnhuRI8qc4mEf/sG+O95fztyPMXcexY84UmHanCt2/yRZvT3Tf66u8RrJjsTEEAy dHOJUUJyIMaMjqe6IKdZPJDq2VXl+yL/TcHPjltSv7WHE2rgsP0NxIQWicG9M6LO4oPf YDVFk/7AzSOkshR1EsWQwKLb8/bGLdu/ws3MnriXlNGk3xnom+aDqs7jNcBobwKiFLrN 3+PEdJV82YJCLOnYjCEFxeJmSNdLMLbfm+RQ0DoehbFOCaFRCIrhbjr+ROLJhv2M3R3D HZug== 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 f15-v6si15157903pli.194.2018.09.02.02.49.46; Sun, 02 Sep 2018 02:50:17 -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 S1727320AbeIBODF (ORCPT + 99 others); Sun, 2 Sep 2018 10:03:05 -0400 Received: from mga07.intel.com ([134.134.136.100]:58895 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726869AbeIBODE (ORCPT ); Sun, 2 Sep 2018 10:03:04 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Sep 2018 02:47:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,319,1531810800"; d="scan'208";a="69718295" Received: from sai-dev-mach.sc.intel.com ([143.183.140.52]) by orsmga007.jf.intel.com with ESMTP; 02 Sep 2018 02:47:46 -0700 From: Sai Praneeth Prakhya To: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ricardo.neri@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 V2 3/6] x86/efi: Permanently save the EFI_MEMORY_MAP passed by the firmware Date: Sun, 2 Sep 2018 02:46:31 -0700 Message-Id: <1535881594-25469-4-git-send-email-sai.praneeth.prakhya@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1535881594-25469-1-git-send-email-sai.praneeth.prakhya@intel.com> References: <1535881594-25469-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_ACCESS 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..d9e5d9a6d138 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_ACCESS +extern void __init efi_save_original_memmap(void); +#else +static inline void __init efi_save_original_memmap(void) { } +#endif /* CONFIG_EFI_WARN_ON_ILLEGAL_ACCESS */ + 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..7fd53fa8c4dd 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_ACCESS + +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_ACCESS */ -- 2.7.4