From patchwork Thu Oct 3 21:23:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Edgecombe, Rick P" X-Patchwork-Id: 11173433 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 74C8515AB for ; Thu, 3 Oct 2019 21:39:25 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 422B4215EA for ; Thu, 3 Oct 2019 21:39:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 422B4215EA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 2AFBD8E000B; Thu, 3 Oct 2019 17:39:06 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 236E68E000F; Thu, 3 Oct 2019 17:39:06 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0B39E8E000B; Thu, 3 Oct 2019 17:39:05 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0191.hostedemail.com [216.40.44.191]) by kanga.kvack.org (Postfix) with ESMTP id C0A248E000D for ; Thu, 3 Oct 2019 17:39:05 -0400 (EDT) Received: from smtpin03.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with SMTP id 6B2A7824CA3D for ; Thu, 3 Oct 2019 21:39:05 +0000 (UTC) X-FDA: 76003789050.03.feet66_6c63f50a18701 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,rick.p.edgecombe@intel.com,:kvm@vger.kernel.org:linux-kernel@vger.kernel.org:x86@kernel.org::luto@kernel.org:peterz@infradead.org:dave.hansen@intel.com:pbonzini@redhat.com:sean.j.christopherson@intel.com:keescook@chromium.org:kristen@linux.intel.com:deneen.t.dock@intel.com:rick.p.edgecombe@intel.com,RULES_HIT:30054:30064:30070,0,RBL:134.134.136.20:@intel.com:.lbl8.mailshell.net-62.50.0.100 64.95.201.95,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:ft,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:2,LUA_SUMMARY:none X-HE-Tag: feet66_6c63f50a18701 X-Filterd-Recvd-Size: 4849 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by imf49.hostedemail.com (Postfix) with ESMTP for ; Thu, 3 Oct 2019 21:39:04 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 14:38:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,253,1566889200"; d="scan'208";a="186051647" Received: from linksys13920.jf.intel.com (HELO rpedgeco-DESK5.jf.intel.com) ([10.54.75.11]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 14:38:58 -0700 From: Rick Edgecombe To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, x86@kernel.org, linux-mm@kvack.org, luto@kernel.org, peterz@infradead.org, dave.hansen@intel.com, pbonzini@redhat.com, sean.j.christopherson@intel.com, keescook@chromium.org Cc: kristen@linux.intel.com, deneen.t.dock@intel.com, Rick Edgecombe Subject: [RFC PATCH 12/13] mmap: Add XO support for KVM XO Date: Thu, 3 Oct 2019 14:23:59 -0700 Message-Id: <20191003212400.31130-13-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191003212400.31130-1-rick.p.edgecombe@intel.com> References: <20191003212400.31130-1-rick.p.edgecombe@intel.com> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The KVM XO feature enables the ability to create execute-only virtual memory. Use this feature to create XO memory when PROT_EXEC and not PROT_READ, as the behavior in the case of protection keys for userspace and some arm64 platforms. In the case of the ability to create execute only memory with protection keys AND the ability to create native execute only memory, use the KVM XO method of creating execute only memory to save a protection key. Set the values of the __P100 and __S100 in protection_map during boot instead of statically because the actual KVM XO bit in the PTE is determinted at boot time and so can't be known at compile time. Signed-off-by: Rick Edgecombe --- arch/x86/include/asm/pgtable_types.h | 2 ++ arch/x86/kernel/head64.c | 3 +++ mm/mmap.c | 30 +++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index d3c92c992089..fe976b4f0132 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -176,6 +176,8 @@ enum page_cache_mode { _PAGE_ACCESSED | _PAGE_NX) #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ _PAGE_ACCESSED) +#define PAGE_EXECONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \ + _PAGE_ACCESSED | _PAGE_NR) #define __PAGE_KERNEL_EXEC \ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 7091702a7bec..69772b6e1810 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -133,6 +133,9 @@ static void __head check_kvmxo_support(unsigned long physaddr) *fixup_int(&__pgtable_kvmxo_enabled, physaddr) = 1; *fixup_int(&__pgtable_kvmxo_bit, physaddr) = physbits; + + protection_map[4] = PAGE_EXECONLY; + protection_map[12] = PAGE_EXECONLY; } #else /* CONFIG_KVM_XO */ static void __head check_kvmxo_support(unsigned long physaddr) { } diff --git a/mm/mmap.c b/mm/mmap.c index 7e8c3e8ae75f..034ffa0255b2 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1379,6 +1379,29 @@ static inline bool file_mmap_ok(struct file *file, struct inode *inode, return true; } +static inline int get_pkey(unsigned long flags) +{ + const unsigned long p_xo = pgprot_val(protection_map[4]); + const unsigned long p_xr = pgprot_val(protection_map[5]); + const unsigned long s_xo = pgprot_val(protection_map[12]); + const unsigned long s_xr = pgprot_val(protection_map[13]); + int pkey; + + /* Prefer non-pkey XO capability if available, to save a pkey */ + + if (flags & MAP_PRIVATE && (p_xo != p_xr)) + return 0; + + if (flags & MAP_SHARED && (s_xo != s_xr)) + return 0; + + pkey = execute_only_pkey(current->mm); + if (pkey < 0) + pkey = 0; + + return pkey; +} + /* * The caller must hold down_write(¤t->mm->mmap_sem). */ @@ -1440,11 +1463,8 @@ unsigned long do_mmap(struct file *file, unsigned long addr, return -EEXIST; } - if (prot == PROT_EXEC) { - pkey = execute_only_pkey(mm); - if (pkey < 0) - pkey = 0; - } + if (prot == PROT_EXEC) + pkey = get_pkey(flags); /* Do simple checking here so the lower-level routines won't have * to. we assume access permissions have been handled by the open