From patchwork Tue Oct 17 17:10:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George Dunlap X-Patchwork-Id: 10012585 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2D99360567 for ; Tue, 17 Oct 2017 17:16:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 13FD3289A3 for ; Tue, 17 Oct 2017 17:16:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 08013289AA; Tue, 17 Oct 2017 17:16:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 028B6289A6 for ; Tue, 17 Oct 2017 17:16:32 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1e4VRJ-0005UX-EP; Tue, 17 Oct 2017 17:14:01 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1e4VRI-0005UO-2I for xen-devel@lists.xenproject.org; Tue, 17 Oct 2017 17:14:00 +0000 Received: from [85.158.143.35] by server-3.bemta-6.messagelabs.com id C6/F2-14867-75A36E95; Tue, 17 Oct 2017 17:13:59 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrJLMWRWlGSWpSXmKPExsXitHRDpG6Y1bN Ig903NSy+b5nM5MDocfjDFZYAxijWzLyk/IoE1oz/Ux6yFWz1rri35xdjA+Me4y5GTg4JAX+J lbc7mUFsNgE9iXnHv7J0MXJwiAioSNzea9DFyMXBLLCTSeL2wkZWkBphAWuJE5fus4PYLAKqE hNvtoP18gLFf75/xgIxU17i/YL7jCC2EFDN4gdH2SFqBCVOznwCVsMsICFx8MUL5gmM3LOQpG YhSS1gZFrFqFGcWlSWWqRraKaXVJSZnlGSm5iZo2toYKaXm1pcnJiempOYVKyXnJ+7iREYDAx AsIPx/saAQ4ySHExKorzOhk8ihfiS8lMqMxKLM+KLSnNSiw8xynBwKEnwPrd4FikkWJSanlqR lpkDDEuYtAQHj5IIr5klUJq3uCAxtzgzHSJ1ilGXo+Pm3T9MQix5+XmpUuK84iBFAiBFGaV5c CNgMXKJUVZKmJcR6CghnoLUotzMElT5V4ziHIxKwrxMIFN4MvNK4Da9AjqCCeiIdU5PQI4oSU RISTUwupY1GK3wi3KpsdR7YL13QUWh4PGQ+QUrbrfWT2G4xjZLcvH3a60HBDd8tUveK2jzac4 Vs7QTfgtCfqlfTZDqe8dc89Whc+KnRTGpBYtXPMowXfJ3opTenWOPFu3ny1H+bS/q07j4fMXH rueMrN1LDjPxzgiJbjw17/Rm7Y0XLmf5P2MLkrvkpsRSnJFoqMVcVJwIAJ9/NI6MAgAA X-Env-Sender: prvs=456766a8c=George.Dunlap@citrix.com X-Msg-Ref: server-6.tower-21.messagelabs.com!1508260436!54578299!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 2910 invoked from network); 17 Oct 2017 17:13:58 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-6.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 17 Oct 2017 17:13:58 -0000 X-IronPort-AV: E=Sophos;i="5.43,391,1503360000"; d="scan'208";a="446709854" From: George Dunlap To: Date: Tue, 17 Oct 2017 18:10:37 +0100 Message-ID: <20171017171037.436-1-george.dunlap@citrix.com> X-Mailer: git-send-email 2.14.2 MIME-Version: 1.0 Cc: Stefano Stabellini , Wei Liu , Konrad Wilk , Andrew Cooper , George Dunlap , Julien Grall , Jan Beulich , Ian Jackson Subject: [Xen-devel] [PATCH] x86/mm: Make PV linear pagetables optional X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Allowing pagetables to point to other pagetables of the same level (often called 'linear pagetables') has been included in Xen since its inception; but recently it has been the source of a number of subtle reference-counting bugs. It is not used by Linux or MiniOS; but it used used by NetBSD and Novell Netware. There are significant numbers of people who are never going to use the feature, along with significant numbers who need the feature. Add a Kconfig option for the feature (default to 'y'). Also add a command-line option to control whether PV linear pagetables are allowed (default to 'true'). In order to make the code clean: - Introduce LPT_ASSERT(), which only exists if CONFIG_PV_LINEAR_PT is defined - Introduce zero_linear_entries() to set page->linear_pt_count to zero (or do nothing, as appropriate) Reported-by: Jann Horn Signed-off-by: George Dunlap --- Changes since XSA - Add a Kconfig option - Default to 'on' (rather than 'off'). Release justification: This was originally part of a security fix embargoed until after the freeze date; it wasn't checked in with the other security patches in order to allow a discussion about the default. CC: Ian Jackson CC: Wei Liu CC: Andrew Cooper CC: Jan Beulich CC: Stefano Stabellini CC: Konrad Wilk CC: Julien Grall --- docs/misc/xen-command-line.markdown | 16 ++++++++++++++++ xen/arch/Kconfig | 1 + xen/arch/arm/mm.c | 1 + xen/arch/x86/Kconfig | 21 ++++++++++++++++++++ xen/arch/x86/mm.c | 38 +++++++++++++++++++++++++++++++++---- xen/include/asm-x86/mm.h | 5 +++++ 6 files changed, 78 insertions(+), 4 deletions(-) diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index eb4995e68b..952368d3be 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -1422,6 +1422,22 @@ The following resources are available: CDP, one COS will corespond two CBMs other than one with CAT, due to the sum of CBMs is fixed, that means actual `cos_max` in use will automatically reduce to half when CDP is enabled. + +### pv-linear-pt +> `= ` + +> Default: `false` + +Allow PV guests to have pagetable entries pointing to other pagetables +of the same level (i.e., allowing L2 PTEs to point to other L2 pages). +This technique is often called "linear pagetables", and is sometimes +used to allow operating systems a simple way to consistently map the +current process's pagetables into its own virtual address space. + +Linux and MiniOS don't use this technique. NetBSD and Novell Netware +do; there may be other custom operating systems which do. If you're +certain you don't plan on having PV guests which use this feature, +turning it off can reduce the attack surface. ### rcu-idle-timer-period-ms > `= ` diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig index cf0acb7e89..47287a4985 100644 --- a/xen/arch/Kconfig +++ b/xen/arch/Kconfig @@ -6,3 +6,4 @@ config NR_CPUS default "128" if ARM ---help--- Specifies the maximum number of physical CPUs which Xen will support. + diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 3c328e2df5..199155fcd8 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -42,6 +42,7 @@ #include #include + struct domain *dom_xen, *dom_io, *dom_cow; /* Override macros from asm/page.h to make them work with mfn_t */ diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index 64955dc017..e2fcbaf5cc 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -97,6 +97,27 @@ config TBOOT Technology (TXT) If unsure, say Y. + +config PV_LINEAR_PT + bool "Support for PV linear pagetables" + depends on PV + default y + ---help--- + Linear pagetables (also called "recursive pagetables") refers + to the practice of a guest operating system having pagetable + entries pointing to other pagetables of the same level (i.e., + allowing L2 PTEs to point to other L2 pages). Some operating + systems use it as a simple way to consisently map the current + process's pagetables into its own virtual address space. + + Linux and MiniOS don't use this technique. NetBSD and Novell + Netware do; there may be other custom operating systems which + do. If you're certain you don't plan on having PV guests + which use this feature, turning it off can reduce the attack + surface. + + If unsure, say Y. + endmenu source "common/Kconfig" diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 62d313e3f5..5881b64608 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -587,6 +587,12 @@ static void put_data_page( put_page(page); } +#ifdef CONFIG_PV_LINEAR_PT +static void zero_linear_entries(struct page_info *pg) +{ + pg->linear_pt_count = 0; +} + static bool inc_linear_entries(struct page_info *pg) { typeof(pg->linear_pt_count) nc = read_atomic(&pg->linear_pt_count), oc; @@ -654,6 +660,9 @@ static void dec_linear_uses(struct page_info *pg) * frame if it is mapped by a different root table. This is sufficient and * also necessary to allow validation of a root table mapping itself. */ +static bool __read_mostly pv_linear_pt_enable = true; +boolean_param("pv-linear-pt", pv_linear_pt_enable); + #define define_get_linear_pagetable(level) \ static int \ get_##level##_linear_pagetable( \ @@ -663,6 +672,13 @@ get_##level##_linear_pagetable( \ struct page_info *page; \ unsigned long pfn; \ \ + if ( !pv_linear_pt_enable ) \ + { \ + gdprintk(XENLOG_WARNING, \ + "Attempt to create linear p.t. (feature disabled)\n"); \ + return 0; \ + } \ + \ if ( (level##e_get_flags(pde) & _PAGE_RW) ) \ { \ gdprintk(XENLOG_WARNING, \ @@ -719,6 +735,20 @@ get_##level##_linear_pagetable( \ \ return 1; \ } +#define LPT_ASSERT ASSERT +#else +#define define_get_linear_pagetable(level) \ +static int \ +get_##level##_linear_pagetable( \ + level##_pgentry_t pde, unsigned long pde_pfn, struct domain *d) \ +{ \ + return 0; \ +} +#define zero_linear_entries(pg) +#define dec_linear_uses(pg) +#define dec_linear_entries(pg) +#define LPT_ASSERT(x) +#endif bool is_iomem_page(mfn_t mfn) @@ -2260,7 +2290,7 @@ static int _put_final_page_type(struct page_info *page, unsigned long type, dec_linear_uses(page); dec_linear_entries(ptpg); } - ASSERT(!page->linear_pt_count || page_get_owner(page)->is_dying); + LPT_ASSERT(!page->linear_pt_count || page_get_owner(page)->is_dying); set_tlbflush_timestamp(page); smp_wmb(); page->u.inuse.type_info--; @@ -2330,8 +2360,8 @@ static int _put_page_type(struct page_info *page, bool preemptible, * necessary anymore for a dying domain. */ ASSERT(page_get_owner(page)->is_dying); - ASSERT(page->linear_pt_count < 0); - ASSERT(ptpg->linear_pt_count > 0); + LPT_ASSERT(page->linear_pt_count < 0); + LPT_ASSERT(ptpg->linear_pt_count > 0); ptpg = NULL; } @@ -2508,7 +2538,7 @@ static int __get_page_type(struct page_info *page, unsigned long type, page->nr_validated_ptes = 0; page->partial_pte = 0; } - page->linear_pt_count = 0; + zero_linear_entries(page); rc = alloc_page_type(page, type, preemptible); } diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 26f0153164..7825f36316 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -177,10 +177,15 @@ struct page_info * in use. */ struct { +#ifdef CONFIG_PV_LINEAR_PT u16 nr_validated_ptes:PAGETABLE_ORDER + 1; u16 :16 - PAGETABLE_ORDER - 1 - 2; s16 partial_pte:2; s16 linear_pt_count; +#else + u16 nr_validated_ptes; + s8 partial_pte; +#endif }; /*