From patchwork Tue Jan 31 13:21:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 92985 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1923828qgi; Tue, 31 Jan 2017 05:27:49 -0800 (PST) X-Received: by 10.99.97.196 with SMTP id v187mr30578061pgb.175.1485869269464; Tue, 31 Jan 2017 05:27:49 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x66si11218392pgb.260.2017.01.31.05.27.49; Tue, 31 Jan 2017 05:27:49 -0800 (PST) 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; 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 S1752534AbdAaN1m (ORCPT + 25 others); Tue, 31 Jan 2017 08:27:42 -0500 Received: from mail-wm0-f47.google.com ([74.125.82.47]:35049 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752120AbdAaN0C (ORCPT ); Tue, 31 Jan 2017 08:26:02 -0500 Received: by mail-wm0-f47.google.com with SMTP id b65so79138613wmf.0 for ; Tue, 31 Jan 2017 05:26:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CQI7XR1zjv/07TVSGLNsjbyRI7VKut/4S3v40/uL4LU=; b=AxY4PkeFbFT7DJwcRMxWuMjQuvyeYwqhDkaYQrTXZHAMc3vnHp0hrL9cAYaZVI1Qj4 tpKzG82B5N3PXhQyINqmPvfETA7mUX6qAPfHz89yO/LaMvLiJWmAaIwq/VIA7Hpt5Gku TT6w6ZljH+M/L8X2tsn8WDcBDHGFR8ClZuhGs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CQI7XR1zjv/07TVSGLNsjbyRI7VKut/4S3v40/uL4LU=; b=t8ClnQcoYvdAhP+F87di5Yl5ghIvkI47B/eSNpo71CRf2E2fFn7JxOoj1fOOdn4k2U /8OgDNKRt+4sCZ6lsnjwKuSwyr22KJ1cvvkYRQyft80GI9wcBDcwJ+rI2O3DKc3UFfrk MkuDhSG5+mc8sQFdCMPP4cZfTsV1aXKlqJO9ja1plM/UlRjxpBZdyTruY+bvWOx2UI6s dfSTSg4EORq7b0PYwtNHWAy/cvvneTmvUNJ4DIguCs05TIvvL3+L8CgEYMJPhDeE0RbK njV7veo7u2Z5CpEXLCb+py+o7cdgTjY78cNSC/ecL9poTMPTDsTN9fI2+jSo+NI+e0WR G9mw== X-Gm-Message-State: AIkVDXLeNRAesUZYfjm+370mgwZkMBXtqngpy//m6AceDFC3sD6IPyaowvt9SVZ1qzXhfJ0P X-Received: by 10.223.164.66 with SMTP id e2mr23334231wra.47.1485869160680; Tue, 31 Jan 2017 05:26:00 -0800 (PST) Received: from localhost.localdomain ([105.130.17.13]) by smtp.gmail.com with ESMTPSA id i73sm23961714wmd.11.2017.01.31.05.25.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 31 Jan 2017 05:26:00 -0800 (PST) From: Ard Biesheuvel To: linux-kernel@vger.kernel.org, Ingo Molnar , Thomas Gleixner , "H . Peter Anvin" Cc: Sai Praneeth , Ard Biesheuvel , linux-efi@vger.kernel.org, "Lee, Chun-Yi" , Borislav Petkov , Ricardo Neri , Ravi Shankar , Fenghua Yu , Matt Fleming Subject: [PATCH 05/10] x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE Date: Tue, 31 Jan 2017 13:21:37 +0000 Message-Id: <1485868902-20401-6-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485868902-20401-1-git-send-email-ard.biesheuvel@linaro.org> References: <1485868902-20401-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sai Praneeth UEFI v2.6 introduces EFI_MEMORY_ATTRIBUTES_TABLE which describes memory protections that may be applied to EFI Runtime code and data regions by kernel. This enables kernel to map these regions more strictly thereby increasing security. Presently, the only valid bits for attribute field of a memory descriptor are EFI_MEMORY_RO and EFI_MEMORY_XP, hence use these bits to update mappings in efi_pgd. UEFI specification recommends to use this feature instead of EFI_PROPERTIES_TABLE and hence while updating efi mappings we first check for EFI_MEMORY_ATTRIBUTES_TABLE and if it's present we update mappings according to this table and hence disregarding EFI_PROPERTIES_TABLE even if it's published by firmware. We consider EFI_PROPERTIES_TABLE only when EFI_MEMORY_ATTRIBUTES_TABLE is absent. Signed-off-by: Sai Praneeth Prakhya Cc: "Lee, Chun-Yi" Cc: Borislav Petkov Cc: Ricardo Neri Cc: Ard Biesheuvel Cc: Ravi Shankar Cc: Fenghua Yu Signed-off-by: Matt Fleming Signed-off-by: Ard Biesheuvel --- arch/x86/platform/efi/efi_64.c | 64 +++++++++++++++++++++++++++++++++++------- drivers/firmware/efi/memattr.c | 5 +++- 2 files changed, 58 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 319148bd4b05..ee966aaf51b2 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -398,10 +398,44 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len) efi_setup = phys_addr + sizeof(struct setup_data); } -void __init efi_runtime_update_mappings(void) +static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf) { unsigned long pfn; pgd_t *pgd = efi_pgd; + int err1, err2; + + /* Update the 1:1 mapping */ + pfn = md->phys_addr >> PAGE_SHIFT; + err1 = kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, md->num_pages, pf); + if (err1) { + pr_err("Error while updating 1:1 mapping PA 0x%llx -> VA 0x%llx!\n", + md->phys_addr, md->virt_addr); + } + + err2 = kernel_map_pages_in_pgd(pgd, pfn, md->virt_addr, md->num_pages, pf); + if (err2) { + pr_err("Error while updating VA mapping PA 0x%llx -> VA 0x%llx!\n", + md->phys_addr, md->virt_addr); + } + + return err1 || err2; +} + +static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *md) +{ + unsigned long pf = 0; + + if (md->attribute & EFI_MEMORY_XP) + pf |= _PAGE_NX; + + if (!(md->attribute & EFI_MEMORY_RO)) + pf |= _PAGE_RW; + + return efi_update_mappings(md, pf); +} + +void __init efi_runtime_update_mappings(void) +{ efi_memory_desc_t *md; if (efi_enabled(EFI_OLD_MEMMAP)) { @@ -410,6 +444,24 @@ void __init efi_runtime_update_mappings(void) return; } + /* + * Use EFI Memory Attribute Table for mapping permissions if it + * exists, since it is intended to supersede EFI_PROPERTIES_TABLE. + */ + if (efi_enabled(EFI_MEM_ATTR)) { + efi_memattr_apply_permissions(NULL, efi_update_mem_attr); + return; + } + + /* + * EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace + * EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update + * permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not + * published by firmware. Even if we find a buggy implementation of + * EFI_MEMORY_ATTRIBUTES_TABLE don't fall back to + * EFI_PROPERTIES_TABLE because of the same above mentioned reason. + */ + if (!efi_enabled(EFI_NX_PE_DATA)) return; @@ -430,15 +482,7 @@ void __init efi_runtime_update_mappings(void) (md->type != EFI_RUNTIME_SERVICES_CODE)) pf |= _PAGE_RW; - /* Update the 1:1 mapping */ - pfn = md->phys_addr >> PAGE_SHIFT; - if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, md->num_pages, pf)) - pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", - md->phys_addr, md->virt_addr); - - if (kernel_map_pages_in_pgd(pgd, pfn, md->virt_addr, md->num_pages, pf)) - pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", - md->phys_addr, md->virt_addr); + efi_update_mappings(md, pf); } } diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c index 402197460507..8986757eafaf 100644 --- a/drivers/firmware/efi/memattr.c +++ b/drivers/firmware/efi/memattr.c @@ -175,8 +175,11 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, md.phys_addr + size - 1, efi_md_typeattr_format(buf, sizeof(buf), &md)); - if (valid) + if (valid) { ret = fn(mm, &md); + if (ret) + pr_err("Error updating mappings, skipping subsequent md's\n"); + } } memunmap(tbl); return ret;