From patchwork Wed Oct 26 10:20:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13020436 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 24B48FA3740 for ; Wed, 26 Oct 2022 10:20:50 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.430420.682100 (Exim 4.92) (envelope-from ) id 1ondWR-0004rV-N6; Wed, 26 Oct 2022 10:20:31 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 430420.682100; Wed, 26 Oct 2022 10:20:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWR-0004rO-K7; Wed, 26 Oct 2022 10:20:31 +0000 Received: by outflank-mailman (input) for mailman id 430420; Wed, 26 Oct 2022 10:20:29 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWP-0004c6-JA for xen-devel@lists.xenproject.org; Wed, 26 Oct 2022 10:20:29 +0000 Received: from esa4.hc3370-68.iphmx.com (esa4.hc3370-68.iphmx.com [216.71.155.144]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id cfd4c801-5517-11ed-91b5-6bf2151ebd3b; Wed, 26 Oct 2022 12:20:28 +0200 (CEST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: cfd4c801-5517-11ed-91b5-6bf2151ebd3b DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1666779627; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UKcW3nevq717wcPG1BpUjMEd9z82OdectilgGlr6jBY=; b=EFJbnd+HnLQn6QNs0GvCqGaBVh2+A/ZBgdMBVYE2NYUHJdAllUk6S1cS biWv/h0oiaRBdQVTvwWcZOFOkCdn0CmVFOekQjZx3NrlDpZxO7bljXv2p XEsn6BgFtVJzA14/lGol/g5boszjYFkk+nLhVtNIRZspeOVnq/llRB2xm U=; Authentication-Results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none X-SBRS: 5.1 X-MesageID: 86061067 X-Ironport-Server: esa4.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-Data: A9a23:2Kfluaq6JlESVd4Y40UExfz5xx9eBmKIZRIvgKrLsJaIsI4StFCzt garIBmHPK2DM2HwL9p+bY+zoBlXv5HQzoIwHAVrrCE1Q3hH8ZuZCYyVIHmrMnLJJKUvbq7FA +Y2MYCccZ9uHhcwgj/3b9ANeFEljfngqoLUUbKCYGYpLeNdYH9JoQp5nOIkiZJfj9G8Agec0 fv/uMSaM1K+s9JOGjt8B5mr9VU+4ZwehBtC5gZkPKgR4geH/5UoJMl3yZ+ZfiOQrrZ8RoZWd 86bpJml82XQ+QsaC9/Nut4XpWVTH9Y+lSDX4pZnc/DKbipq/0Te4Y5iXBYoUm9Fii3hojxE4 I4lWapc6+seFvakdOw1C3G0GszlVEFM0OevzXOX6aR/w6BaGpdFLjoH4EweZOUlFuhL7W5m5 8UBEQwyc0q6isHv3Y2ZcqpFjOstM5y+VG8fkikIITDxCP8nRdbIQrnQ5M8e1zA17ixMNa+AP YxDM2MpNUmeJU0UUrsUIMtWcOOAr3/zaTBH7nmSorI6+TP7xw1tyrn9dtHSf7RmQO0FwB7G/ zqYoAwVBDkEKdKx7RCoyUu+2NLSjHvnSZpIO/qno6sCbFq7mTVIVUx+uUGAice+jkmyStdOM Xs+8yAlrbUx3EGzR9y7VBq9yFaGoxodVtx4A+A8rgaXxcL8wwufHHlCcTdHZ/QvrspwTjsvv neDksn1HzVpvPuQQGiE67aPhTqoPG4eKmpqTTQfUQIP7t3noYcyphHCVNBuFOiylNKdMSr9y C2QrTQvr6Uei4gMzarT1UDKhXegq4bESiYx5x7LRSS14wVhfomnaoe0r1/B4p5oM4KxXlSH+ n8elKC2zsoDEJWMnyylW/gWEfei4PPtDdHHqQcxRd97rW3roiP9O9ALiN1jGKt3GtQ9YAbVX 1KJgA5yvYJsHkPpRKVYbZ3kXqzG0pPcPdjiU/nVaP9HbZ5waBKL8UlSWKKA44z+uBNyyP9iY P93Ze7pVC9HUvo/kFJaUs9HidcWKjYCKXQ/rHwR5zCuyvKgaXGcUt/p23PeP7livMtoTOg4m uuz1vdmKT0FDoUSgQGNq+b/yGzmylBiXPjLRzR/LLLrH+afMDhJ5wXt6b0gYZd5uK9ei/3F+ HqwMmcBlgSh2iedeFzTMCg+AF8KYXqYhStlVRHAwH7ygyRzCWpRxPt3m2QLkUkPq7U4kK8co wgtcMScGPVfIgkrCBxEBaQRWLdKLUzx7SrXZnLNSGFmL/Zdq/nhp4aMkv3Hr3JVUEJadKIW/ tWd6+8sacBYHlU/UpuLOZpCDTqZ5BAgpQ67ZGOQSvE7Rakm2NICx/DZ5hPvH/wxFA== IronPort-HdrOrdr: A9a23:vDmGwq4BXed/QzFLugPXwM7XdLJyesId70hD6qhwISY7TiX+rb HJoB17726StN9/YhAdcLy7VZVoBEmsl6KdgrNhWYtKPjOHhILAFugLhuHfKn/bakjDH4ZmpN 5dmsNFZuEYY2IXsS+D2njaL+od X-IronPort-AV: E=Sophos;i="5.95,214,1661832000"; d="scan'208";a="86061067" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Xen Security Team , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Wei Liu , Stefano Stabellini , Julien Grall , Volodymyr Babchuk , "Bertrand Marquis" , Henry Wang , "Anthony PERARD" Subject: [PATCH 1/4] xen: Introduce non-broken hypercalls for the p2m pool size Date: Wed, 26 Oct 2022 11:20:15 +0100 Message-ID: <20221026102018.4144-2-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20221026102018.4144-1-andrew.cooper3@citrix.com> References: <20221026102018.4144-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 The existing XEN_DOMCTL_SHADOW_OP_{GET,SET}_ALLOCATION have problems: * All set_allocation() flavours have an overflow-before-widen bug when calculating "sc->mb << (20 - PAGE_SHIFT)". * All flavours have a granularity of of 1M. This was tolerable when the size of the pool could only be set at the same granularity, but is broken now that ARM has a 16-page stopgap allocation in use. * All get_allocation() flavours round up, and in particular turn 0 into 1, meaning the get op returns junk before a successful set op. * The x86 flavours reject the hypercalls before the VM has vCPUs allocated, despite the pool size being a domain property. * Even the hypercall names are long-obsolete. Implement an interface that doesn't suck, which can be first used to unit test the behaviour, and subsequently correct a broken implementation. The old interface will be retired in due course. This is part of XSA-409 / CVE-2022-33747. Signed-off-by: Andrew Cooper --- CC: Xen Security Team CC: Jan Beulich CC: Roger Pau Monné CC: Wei Liu CC: Stefano Stabellini CC: Julien Grall CC: Volodymyr Babchuk CC: Bertrand Marquis CC: Henry Wang CC: Anthony PERARD Name subject to improvement. ABI not. This is the first of many tools ABI changes required to cleanly separate the logical operation from Xen's choice of pagetable size. Future TODOs: * x86 shadow still rounds up. This is buggy as it's a simultaneous equation with tot_pages which varies over time with ballooning. * x86 PV is weird. There are no toolstack interact with the shadow pool size, but the "shadow" pool it does come into existence when logdirty (or pv-l1tf) when first enabled. * The shadow+hap logic is in desperate need of deduping. --- tools/include/xenctrl.h | 3 +++ tools/libs/ctrl/xc_domain.c | 29 +++++++++++++++++++++++++++++ xen/arch/arm/p2m.c | 27 +++++++++++++++++++++++++++ xen/arch/x86/include/asm/hap.h | 1 + xen/arch/x86/include/asm/shadow.h | 4 ++++ xen/arch/x86/mm/hap/hap.c | 10 ++++++++++ xen/arch/x86/mm/paging.c | 39 +++++++++++++++++++++++++++++++++++++++ xen/arch/x86/mm/shadow/common.c | 10 ++++++++++ xen/common/domctl.c | 14 ++++++++++++++ xen/include/public/domctl.h | 26 +++++++++++++++++++++++++- xen/include/xen/domain.h | 3 +++ 11 files changed, 165 insertions(+), 1 deletion(-) diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h index 0c8b4c3aa7a5..f503f03a3927 100644 --- a/tools/include/xenctrl.h +++ b/tools/include/xenctrl.h @@ -893,6 +893,9 @@ long long xc_logdirty_control(xc_interface *xch, unsigned int mode, xc_shadow_op_stats_t *stats); +int xc_get_p2m_mempool_size(xc_interface *xch, uint32_t domid, uint64_t *size); +int xc_set_p2m_mempool_size(xc_interface *xch, uint32_t domid, uint64_t size); + int xc_sched_credit_domain_set(xc_interface *xch, uint32_t domid, struct xen_domctl_sched_credit *sdom); diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c index 14c0420c35be..9ac09cfab036 100644 --- a/tools/libs/ctrl/xc_domain.c +++ b/tools/libs/ctrl/xc_domain.c @@ -706,6 +706,35 @@ long long xc_logdirty_control(xc_interface *xch, return (rc == 0) ? domctl.u.shadow_op.pages : rc; } +int xc_get_p2m_mempool_size(xc_interface *xch, uint32_t domid, uint64_t *size) +{ + int rc; + struct xen_domctl domctl = { + .cmd = XEN_DOMCTL_get_p2m_mempool_size, + .domain = domid, + }; + + rc = do_domctl(xch, &domctl); + if ( rc ) + return rc; + + *size = domctl.u.p2m_mempool.size; + return 0; +} + +int xc_set_p2m_mempool_size(xc_interface *xch, uint32_t domid, uint64_t size) +{ + struct xen_domctl domctl = { + .cmd = XEN_DOMCTL_set_p2m_mempool_size, + .domain = domid, + .u.p2m_mempool = { + .size = size, + }, + }; + + return do_domctl(xch, &domctl); +} + int xc_domain_setmaxmem(xc_interface *xch, uint32_t domid, uint64_t max_memkb) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 94d3b60b1387..4607cde6f0b8 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -100,6 +100,14 @@ unsigned int p2m_get_allocation(struct domain *d) return ROUNDUP(nr_pages, 1 << (20 - PAGE_SHIFT)) >> (20 - PAGE_SHIFT); } +/* Return the size of the pool, in bytes. */ +int arch_get_p2m_mempool_size(struct domain *d, uint64_t *size) +{ + *size = ACCESS_ONCE(d->arch.paging.p2m_total_pages) << PAGE_SHIFT; + + return 0; +} + /* * Set the pool of pages to the required number of pages. * Returns 0 for success, non-zero for failure. @@ -157,6 +165,25 @@ int p2m_set_allocation(struct domain *d, unsigned long pages, bool *preempted) return 0; } +int arch_set_p2m_mempool_size(struct domain *d, uint64_t size) +{ + unsigned long pages = size >> PAGE_SHIFT; + bool preempted = false; + int rc; + + if ( (size & ~PAGE_MASK) || /* Non page-sized request? */ + pages != (size >> PAGE_SHIFT) ) /* 32-bit overflow? */ + return -EINVAL; + + spin_lock(&d->arch.paging.lock); + rc = p2m_set_allocation(d, pages, &preempted); + spin_unlock(&d->arch.paging.lock); + + ASSERT(preempted == (rc == -ERESTART)); + + return rc; +} + int p2m_teardown_allocation(struct domain *d) { int ret = 0; diff --git a/xen/arch/x86/include/asm/hap.h b/xen/arch/x86/include/asm/hap.h index 90dece29deca..14d2f212dab9 100644 --- a/xen/arch/x86/include/asm/hap.h +++ b/xen/arch/x86/include/asm/hap.h @@ -47,6 +47,7 @@ int hap_track_dirty_vram(struct domain *d, extern const struct paging_mode *hap_paging_get_mode(struct vcpu *); int hap_set_allocation(struct domain *d, unsigned int pages, bool *preempted); unsigned int hap_get_allocation(struct domain *d); +int hap_get_allocation_bytes(struct domain *d, uint64_t *size); #endif /* XEN_HAP_H */ diff --git a/xen/arch/x86/include/asm/shadow.h b/xen/arch/x86/include/asm/shadow.h index 1365fe480518..dad876d29499 100644 --- a/xen/arch/x86/include/asm/shadow.h +++ b/xen/arch/x86/include/asm/shadow.h @@ -97,6 +97,8 @@ void shadow_blow_tables_per_domain(struct domain *d); int shadow_set_allocation(struct domain *d, unsigned int pages, bool *preempted); +int shadow_get_allocation_bytes(struct domain *d, uint64_t *size); + #else /* !CONFIG_SHADOW_PAGING */ #define shadow_vcpu_teardown(v) ASSERT(is_pv_vcpu(v)) @@ -108,6 +110,8 @@ int shadow_set_allocation(struct domain *d, unsigned int pages, ({ ASSERT_UNREACHABLE(); -EOPNOTSUPP; }) #define shadow_set_allocation(d, pages, preempted) \ ({ ASSERT_UNREACHABLE(); -EOPNOTSUPP; }) +#define shadow_get_allocation_bytes(d, size) \ + ({ ASSERT_UNREACHABLE(); -EOPNOTSUPP; }) static inline void sh_remove_shadows(struct domain *d, mfn_t gmfn, int fast, int all) {} diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index f809ea9aa6ae..50c3d6e63fa5 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -345,6 +345,16 @@ unsigned int hap_get_allocation(struct domain *d) + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0)); } +int hap_get_allocation_bytes(struct domain *d, uint64_t *size) +{ + unsigned long pages = (d->arch.paging.hap.total_pages + + d->arch.paging.hap.p2m_pages); + + *size = pages << PAGE_SHIFT; + + return 0; +} + /* Set the pool of pages to the required number of pages. * Returns 0 for success, non-zero for failure. */ int hap_set_allocation(struct domain *d, unsigned int pages, bool *preempted) diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 3a355eee9ca3..b3f7c46e1dfd 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -977,6 +977,45 @@ int __init paging_set_allocation(struct domain *d, unsigned int pages, } #endif +int arch_get_p2m_mempool_size(struct domain *d, uint64_t *size) +{ + int rc; + + if ( is_pv_domain(d) ) + return -EOPNOTSUPP; + + if ( hap_enabled(d) ) + rc = hap_get_allocation_bytes(d, size); + else + rc = shadow_get_allocation_bytes(d, size); + + return rc; +} + +int arch_set_p2m_mempool_size(struct domain *d, uint64_t size) +{ + unsigned long pages = size >> PAGE_SHIFT; + bool preempted = false; + int rc; + + if ( is_pv_domain(d) ) + return -EOPNOTSUPP; + + if ( size & ~PAGE_MASK ) /* Non page-sized request? */ + return -EINVAL; + + ASSERT(paging_mode_enabled(d)); + + paging_lock(d); + if ( hap_enabled(d) ) + rc = hap_set_allocation(d, pages, &preempted); + else + rc = shadow_set_allocation(d, pages, &preempted); + paging_unlock(d); + + return preempted ? -ERESTART : rc; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index badfd53c6b23..d190601c4424 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1427,6 +1427,16 @@ static unsigned int shadow_get_allocation(struct domain *d) + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0)); } +int shadow_get_allocation_bytes(struct domain *d, uint64_t *size) +{ + unsigned long pages = (d->arch.paging.shadow.total_pages + + d->arch.paging.shadow.p2m_pages); + + *size = pages << PAGE_SHIFT; + + return 0; +} + /**************************************************************************/ /* Hash table for storing the guest->shadow mappings. * The table itself is an array of pointers to shadows; the shadows are then diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 69fb9abd346f..8f318b830185 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -874,6 +874,20 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) ret = iommu_do_domctl(op, d, u_domctl); break; + case XEN_DOMCTL_get_p2m_mempool_size: + ret = arch_get_p2m_mempool_size(d, &op->u.p2m_mempool.size); + if ( !ret ) + copyback = 1; + break; + + case XEN_DOMCTL_set_p2m_mempool_size: + ret = arch_set_p2m_mempool_size(d, op->u.p2m_mempool.size); + + if ( ret == -ERESTART ) + ret = hypercall_create_continuation( + __HYPERVISOR_domctl, "h", u_domctl); + break; + default: ret = arch_do_domctl(op, d, u_domctl); break; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index b2ae839c3632..7da09d5925c8 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -214,7 +214,10 @@ struct xen_domctl_getpageframeinfo3 { /* Return the bitmap but do not modify internal copy. */ #define XEN_DOMCTL_SHADOW_OP_PEEK 12 -/* Memory allocation accessors. */ +/* + * Memory allocation accessors. These APIs are broken and will be removed. + * Use XEN_DOMCTL_{get,set}_p2m_mempool_size instead. + */ #define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 #define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 @@ -946,6 +949,24 @@ struct xen_domctl_cacheflush { xen_pfn_t start_pfn, nr_pfns; }; +/* + * XEN_DOMCTL_get_p2m_mempool_size / XEN_DOMCTL_set_p2m_mempool_size. + * + * Get or set the P2M memory pool size. The size is in bytes. + * + * The P2M memory pool is a dedicated pool of memory for managing the guest + * physical -> host physical mappings, usually containing pagetables. + * Implementation details cause there to be a minimum granularity, usually the + * size of pagetables used by Xen. Users of this interface are required to + * identify the granularity by other means. + * + * The set operation can fail midway through the request (e.g. Xen running out + * of memory, no free memory to reclaim from the pool, etc.). + */ +struct xen_domctl_p2m_mempool { + uint64_aligned_t size; /* IN/OUT. Size in bytes. */ +}; + #if defined(__i386__) || defined(__x86_64__) struct xen_domctl_vcpu_msr { uint32_t index; @@ -1274,6 +1295,8 @@ struct xen_domctl { #define XEN_DOMCTL_get_cpu_policy 82 #define XEN_DOMCTL_set_cpu_policy 83 #define XEN_DOMCTL_vmtrace_op 84 +#define XEN_DOMCTL_get_p2m_mempool_size 85 +#define XEN_DOMCTL_set_p2m_mempool_size 86 #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -1335,6 +1358,7 @@ struct xen_domctl { struct xen_domctl_psr_alloc psr_alloc; struct xen_domctl_vuart_op vuart_op; struct xen_domctl_vmtrace_op vmtrace_op; + struct xen_domctl_p2m_mempool p2m_mempool; uint8_t pad[128]; } u; }; diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 2c8116afba27..01aaf4dedbe8 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -98,6 +98,9 @@ void arch_get_info_guest(struct vcpu *, vcpu_guest_context_u); int arch_initialise_vcpu(struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg); int default_initialise_vcpu(struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg); +int arch_get_p2m_mempool_size(struct domain *d, uint64_t *size /* bytes */); +int arch_set_p2m_mempool_size(struct domain *d, uint64_t size /* bytes */); + int domain_relinquish_resources(struct domain *d); void dump_pageframe_info(struct domain *d); From patchwork Wed Oct 26 10:20:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13020435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2DE56C433FE for ; Wed, 26 Oct 2022 10:20:49 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.430422.682122 (Exim 4.92) (envelope-from ) id 1ondWZ-0005QZ-AL; Wed, 26 Oct 2022 10:20:39 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 430422.682122; Wed, 26 Oct 2022 10:20:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWZ-0005QQ-7H; Wed, 26 Oct 2022 10:20:39 +0000 Received: by outflank-mailman (input) for mailman id 430422; Wed, 26 Oct 2022 10:20:38 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWX-0004c6-Of for xen-devel@lists.xenproject.org; Wed, 26 Oct 2022 10:20:37 +0000 Received: from esa5.hc3370-68.iphmx.com (esa5.hc3370-68.iphmx.com [216.71.155.168]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id d3bbc3f4-5517-11ed-91b5-6bf2151ebd3b; Wed, 26 Oct 2022 12:20:35 +0200 (CEST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: d3bbc3f4-5517-11ed-91b5-6bf2151ebd3b DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1666779635; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=R02ZMC1k6phfC4hNr6bv6e+rmMsxG/5mpBaH4ZGEwOQ=; b=GW2gy6Rf5OpvQZjqvAcRmmv1Fqhivd1drAVFA5BIeOClU/NmRtp86TfC bB7djA8kGIjva0Imwbhh0w7ADrSGNQf9FFgz+CjtuvrOjxP8Zaz62/Oj6 x2gcyX8YXyD+awLAIUJubazwtlDirVFoUwj1jSAvFvZrmbLmzokiT4dSk 4=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none X-SBRS: 5.1 X-MesageID: 82629705 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-Data: A9a23:P8i7P6769hNKx18BiYLetQxRtKjHchMFZxGqfqrLsTDasY5as4F+v jRKW2CBMq2JZTOgKI8ja9i//B5V6sDUztZiGgc9rylkHi5G8cbLO4+Ufxz6V8+wwm8vb2o8t plDNYOQRCwQZiWBzvt4GuG59RGQ7YnRGvymTras1hlZHWdMUD0mhQ9oh9k3i4tphcnRKw6Ws Jb5rta31GWNglaYCUpJrfPewP9TlK6q4mlB5gZgPakjUGL2zBH5MrpOfcldEFOgKmVkNrbSb /rOyri/4lTY838FYj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnVaPpIAHOgdcS9qZwChxLid/ jnvWauYEm/FNoWU8AgUvoIx/ytWZcWq85efSZSzXFD6I+QrvBIAzt03ZHzaM7H09c5LHT1iy e4nJwkNVTDcv7yJ6euAeu5V05FLwMnDZOvzu1llxDDdS/0nXYrCU+PB4towMDUY354UW6yEP oxANGQpPE+ojx5nYz/7DLoXmuuyi2a5WDpfsF+P/oI84nTJzRw327/oWDbQUozQG58EwR7Fz o7A10voBggxLu6l8CPG1lWiiffkkBqnW7tHQdVU8dY12QbOlwT/EiY+a1y/pvWoj1+kbPhWI UcU5ykGoLA78QqgSdyVdx+lpH+JuDYMVtwWFPc1gCmtx6zO8kCmD24LZjdbbZots8pebTYnz EOTltXlQzlmqqSISGm1/62R6zi1PEA9NnQebCUJSQ8E5djLo4wpiB/LCNF5H8adldD+BCvx3 yGivCU4wbIJgqYjx6i9uFzKnT+ojpzIVRIuoBXaWHq/6QF0b5LjYJangXDE6d5QIYDfSUOO1 FAmscWD6OEFDbmWiTeABu4KGdmUC+2taWOGxwQ1Rt94qmrrqyXLkZ1sDC9WGFs1HvoWRjDQY HTz5jsP27YKB0utVPoiC26uMPgCwa/lHNXjc/nbaNtSf5R8HDO6EDFSiV24hD60zhV1+U0rE dLCKJv3Uy5GYUhy5GDuL9rxx4PH0czXKYn7YZnghyqq3rOFDJJ+YedUaQDeBgzVAU7tnek0z zq9H5HUo/m8eLekCsUyzWL0BQlTRUXX/bis96Rqmhere2KK4l0JBf7L2q8GcId4halTneqg1 ijjBBEHkgCu3CSdcVjihpVfhFTHBMgXkJ7GFXZ0YQbAN4YLPe5DE5vzh7NoJOJ6pYSPPNZ/T uUfetXoPxi8Ym2vxtjpVrGk9NYKXE3y3WqmZnP1CAXTirY9HmQlDPe/JVCxnMTPZwLq3fYDT 0qIjFiCEMddGlkzZCsUAdr2p26MUbEmsLoadyP1zhN7IS0ALKACx/TNs8IK IronPort-HdrOrdr: A9a23:WsNLS6C5F24WvBXlHemq55DYdb4zR+YMi2TC1yhKJiC9Ffbo8f xG/c5rsiMc5wxxZJhNo7290ey7MBHhHP1OkO0s1NWZPDUO0VHAROoJ0WKh+UyEJ8SXzJ8l6U 4KScZD4bPLYWSS9fyKgzWFLw== X-IronPort-AV: E=Sophos;i="5.95,214,1661832000"; d="scan'208";a="82629705" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Xen Security Team , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Wei Liu , Stefano Stabellini , Julien Grall , Volodymyr Babchuk , "Bertrand Marquis" , Henry Wang , "Anthony PERARD" Subject: [PATCH 2/4] tools/tests: Unit test for p2m pool size Date: Wed, 26 Oct 2022 11:20:16 +0100 Message-ID: <20221026102018.4144-3-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20221026102018.4144-1-andrew.cooper3@citrix.com> References: <20221026102018.4144-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Exercise some basic functionality of the new xc_{get,set}_p2m_mempool_size() hypercalls. This passes on x86, but fails currently on ARM. ARM will be fixed up in future patches. This is part of XSA-409 / CVE-2022-33747. Signed-off-by: Andrew Cooper --- CC: Xen Security Team CC: Jan Beulich CC: Roger Pau Monné CC: Wei Liu CC: Stefano Stabellini CC: Julien Grall CC: Volodymyr Babchuk CC: Bertrand Marquis CC: Henry Wang CC: Anthony PERARD --- tools/tests/Makefile | 1 + tools/tests/p2m-pool/.gitignore | 1 + tools/tests/p2m-pool/Makefile | 42 ++++++++ tools/tests/p2m-pool/test-p2m-pool.c | 181 +++++++++++++++++++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 tools/tests/p2m-pool/.gitignore create mode 100644 tools/tests/p2m-pool/Makefile create mode 100644 tools/tests/p2m-pool/test-p2m-pool.c diff --git a/tools/tests/Makefile b/tools/tests/Makefile index d99146d56a64..7ce8b7b881db 100644 --- a/tools/tests/Makefile +++ b/tools/tests/Makefile @@ -11,6 +11,7 @@ endif SUBDIRS-y += xenstore SUBDIRS-y += depriv SUBDIRS-y += vpci +SUBDIRS-y += p2m-pool .PHONY: all clean install distclean uninstall all clean distclean install uninstall: %: subdirs-% diff --git a/tools/tests/p2m-pool/.gitignore b/tools/tests/p2m-pool/.gitignore new file mode 100644 index 000000000000..cce6d97b1cc8 --- /dev/null +++ b/tools/tests/p2m-pool/.gitignore @@ -0,0 +1 @@ +test-p2m-pool diff --git a/tools/tests/p2m-pool/Makefile b/tools/tests/p2m-pool/Makefile new file mode 100644 index 000000000000..24f348f20582 --- /dev/null +++ b/tools/tests/p2m-pool/Makefile @@ -0,0 +1,42 @@ +XEN_ROOT = $(CURDIR)/../../.. +include $(XEN_ROOT)/tools/Rules.mk + +TARGET := test-p2m-pool + +.PHONY: all +all: $(TARGET) + +.PHONY: clean +clean: + $(RM) -- *.o $(TARGET) $(DEPS_RM) + +.PHONY: distclean +distclean: clean + $(RM) -- *~ + +.PHONY: install +install: all + $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN) + $(INSTALL_PROG) $(TARGET) $(DESTDIR)$(LIBEXEC_BIN) + +.PHONY: uninstall +uninstall: + $(RM) -- $(DESTDIR)$(LIBEXEC_BIN)/$(TARGET) + +CFLAGS += $(CFLAGS_xeninclude) +CFLAGS += $(CFLAGS_libxenctrl) +CFLAGS += $(CFLAGS_libxenforeginmemory) +CFLAGS += $(CFLAGS_libxengnttab) +CFLAGS += $(APPEND_CFLAGS) + +LDFLAGS += $(LDLIBS_libxenctrl) +LDFLAGS += $(LDLIBS_libxenforeignmemory) +LDFLAGS += $(LDLIBS_libxengnttab) +LDFLAGS += $(APPEND_LDFLAGS) + +%.o: Makefile + +$(TARGET): test-p2m-pool.o + $(CC) -o $@ $< $(LDFLAGS) + +-include $(DEPS_INCLUDE) diff --git a/tools/tests/p2m-pool/test-p2m-pool.c b/tools/tests/p2m-pool/test-p2m-pool.c new file mode 100644 index 000000000000..1ffb19eeb420 --- /dev/null +++ b/tools/tests/p2m-pool/test-p2m-pool.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static unsigned int nr_failures; +#define fail(fmt, ...) \ +({ \ + nr_failures++; \ + (void)printf(fmt, ##__VA_ARGS__); \ +}) + +static xc_interface *xch; +static uint32_t domid; + +static struct xen_domctl_createdomain create = { + .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap, + .max_vcpus = 1, + .max_grant_frames = 1, + .grant_opts = XEN_DOMCTL_GRANT_version(1), + + .arch = { +#if defined(__x86_64__) || defined(__i386__) + .emulation_flags = XEN_X86_EMU_LAPIC, +#endif + }, +}; + +static uint64_t default_p2m_size_bytes = +#if defined(__x86_64__) || defined(__i386__) + 256 << 12; /* Only x86 HAP for now. x86 Shadow broken. */ +#elif defined (__arm__) || defined(__aarch64__) + 16 << 12; +#endif + +static void run_tests(void) +{ + xen_pfn_t physmap[] = { 0 }; + uint64_t size_bytes, old_size_bytes; + int rc; + + printf("Test default p2m mempool size\n"); + + rc = xc_get_p2m_mempool_size(xch, domid, &size_bytes); + if ( rc ) + return fail(" Fail: get p2m mempool size: %d - %s\n", + errno, strerror(errno)); + + printf("P2M pool size %"PRIu64" bytes (%"PRIu64"kB, %"PRIu64"MB)\n", + size_bytes, size_bytes >> 10, size_bytes >> 20); + + + /* + * Check that the domain has the expected default allocation size. This + * will fail if the logic in Xen is altered without an equivelent + * adjustment here. + */ + if ( size_bytes != default_p2m_size_bytes ) + return fail(" Fail: size %"PRIu64" != expected size %"PRIu64"\n", + size_bytes, default_p2m_size_bytes); + + + printf("Test that allocate doesn't alter pool size\n"); + + /* + * Populate the domain with some RAM. This will cause more of the p2m + * pool to be used. + */ + old_size_bytes = size_bytes; + + rc = xc_domain_setmaxmem(xch, domid, -1); + if ( rc ) + return fail(" Fail: setmaxmem: : %d - %s\n", + errno, strerror(errno)); + + rc = xc_domain_populate_physmap_exact(xch, domid, 1, 0, 0, physmap); + if ( rc ) + return fail(" Fail: populate physmap: %d - %s\n", + errno, strerror(errno)); + + /* + * Re-get the p2m size. Should not have changed as a consequence of + * populate physmap. + */ + rc = xc_get_p2m_mempool_size(xch, domid, &size_bytes); + if ( rc ) + return fail(" Fail: get p2m mempool size: %d - %s\n", + errno, strerror(errno)); + + if ( old_size_bytes != size_bytes ) + return fail(" Fail: p2m mempool size changed %"PRIu64" => %"PRIu64"\n", + old_size_bytes, size_bytes); + + + + printf("Test bad set size\n"); + + /* + * Check that setting a non-page size results in failure. + */ + rc = xc_set_p2m_mempool_size(xch, domid, size_bytes + 1); + if ( rc != -1 || errno != EINVAL ) + return fail(" Fail: Bad set size: expected -1/EINVAL, got %d/%d - %s\n", + rc, errno, strerror(errno)); + + + printf("Test very large set size\n"); + + /* + * Check that setting a large P2M size succeeds. This is expecting to + * trigger continuations. + */ + rc = xc_set_p2m_mempool_size(xch, domid, 64 << 20); + if ( rc ) + return fail(" Fail: Set size 64MB: %d - %s\n", + errno, strerror(errno)); + + + /* + * Check that the reported size matches what set consumed. + */ + rc = xc_get_p2m_mempool_size(xch, domid, &size_bytes); + if ( rc ) + return fail(" Fail: get p2m mempool size: %d - %s\n", + errno, strerror(errno)); + + if ( size_bytes != 64 << 20 ) + return fail(" Fail: expected mempool size %u, got %"PRIu64"\n", + 64 << 20, size_bytes); +} + +int main(int argc, char **argv) +{ + int rc; + + printf("P2M Shadow memory pool tests\n"); + + xch = xc_interface_open(NULL, NULL, 0); + + if ( !xch ) + err(1, "xc_interface_open"); + + rc = xc_domain_create(xch, &domid, &create); + if ( rc ) + { + if ( errno == EINVAL || errno == EOPNOTSUPP ) + printf(" Skip: %d - %s\n", errno, strerror(errno)); + else + fail(" Domain create failure: %d - %s\n", + errno, strerror(errno)); + goto out; + } + + printf(" Created d%u\n", domid); + + run_tests(); + + rc = xc_domain_destroy(xch, domid); + if ( rc ) + fail(" Failed to destroy domain: %d - %s\n", + errno, strerror(errno)); + out: + return !!nr_failures; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Oct 26 10:20:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13020438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3003AC38A2D for ; Wed, 26 Oct 2022 10:21:05 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.430425.682133 (Exim 4.92) (envelope-from ) id 1ondWq-0006D6-Ji; Wed, 26 Oct 2022 10:20:56 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 430425.682133; Wed, 26 Oct 2022 10:20:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWq-0006Ct-F6; Wed, 26 Oct 2022 10:20:56 +0000 Received: by outflank-mailman (input) for mailman id 430425; Wed, 26 Oct 2022 10:20:55 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWp-0004c6-C0 for xen-devel@lists.xenproject.org; Wed, 26 Oct 2022 10:20:55 +0000 Received: from esa6.hc3370-68.iphmx.com (esa6.hc3370-68.iphmx.com [216.71.155.175]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id de3d0b22-5517-11ed-91b5-6bf2151ebd3b; Wed, 26 Oct 2022 12:20:53 +0200 (CEST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: de3d0b22-5517-11ed-91b5-6bf2151ebd3b DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1666779653; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6JO0wvwDsV/DC/XiuqlUU3zZyv9PlBtYFfVcD+Dl1Yk=; b=ZzKALwUtY2MP2luNc+3vGhB9ir8VR7KrUSPNt9raZQoXsHUyeHE+yggc ubX055S7Um8MmQS8cQBIgtfor8MXhWbWa/hhZgmD42Rw3knt6MHJTFGfm iH9epURcL6Rw0wSQVzo9OYqz/O4bCViZ9hn6iErAe97nXsd6htflt/rMW o=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none X-SBRS: 5.1 X-MesageID: 83149672 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-Data: A9a23:RG+9rq/C2N/jZfLaAU/cDrUDEH6TJUtcMsCJ2f8bNWPcYEJGY0x3n WMWDDqCPvaJYGf2eo0jao3i8k1Q7ZDVmN4yTws6ri48E34SpcT7XtnIdU2Y0wF+jCHgZBk+s 5hBMImowOQcFCK0SsKFa+C5xZVE/fjUAOC6UIYoAwgpLSd8UiAtlBl/rOAwh49skLCRDhiE/ Nj/uKUzAnf8s9JPGj9Suv/rRC9H5qyo4mpA5AJmPJingXeF/5UrJMNHTU2OByOQrrl8RoaSW +vFxbelyWLVlz9F5gSNy+uTnuUiG9Y+DCDW4pZkc/HKbitq/0Te5p0TJvsEAXq7vh3S9zxHJ HehgrTrIeshFvWkdO3wyHC0GQkmVUFN0OevzXRSLaV/ZqAJGpfh66wGMa04AWEX0utHWnt2r qIiEzIcfzKg2+WJ/+ufSPY506zPLOGzVG8eknRpzDWfBvc6W5HTBa7N4Le03h9p2JoIR6yHI ZNEN3w/N3wsYDUWUrsTILs4kP2lmT/UdDpApUjOjaE2/3LS3Ep6172F3N/9KofTGZQLwRzwS mTu5iO+LQ0mapulywGczDX3ic7GhBjyR9dHfFG/3qEz2wDCroAJMzUoUl+8rei8m1SJcdtVI EwJ+QIjtaE3skesS7HVXQC8oXOClg4RXZxXCeJSwCGAzLDFpTmQAGcsRyRELtchsaceTzEwy kWAmd+vADV1qaCUUlqU7LLSpjS3UQAONnMLbyIASQoD4vHgrZs1gxaJScxseIaug9boAzDs0 hiaoS54gK8c5eYb2qP+8V3ZjjaEopnSUhVz9gjRRnii7A5yeMiifYPAwUffxeZNKsCeVFbpl FoultWa7esOJYqQjyHLS+IIdIxF/N7cbmea2wQ2WcB8qXL9oBZPYLy8/hlzFBxzCp1aQwTrc V7xml9W26AKGHm1OPofj52KN+wmyq3pFNLAX//Sb8ZTbpUZSDJr7B2CdmbLgTmzzRFEfbUXf M7CLJ3yVSpy5bFPlmLeegsL7VM8KsnSL0v3TIuz8Rmo2KH2iJW9GeZcawvmggzUAcq5TOTpH zR3bZXiJ/Z3CreWjszrHWk7dAliEJTDLcqqw/G7j8baSuacJEkvCuXK3ZQqcJF/kqJem4/gp y/jBBACkgum3CefdG1mj0yPj5u2A/5CQY8TZ3RwbT5EJVB/CWpQ0EvvX8RuJuR2nACS5fV1U +MEa6297gdnE1z6F8AmRcCl9uRKLU3z7SrXZnrNXdTKV8M5L+A/0oS/JVWHGehnJnffiPbSV JX6jVqKHMReGlUK4QS/QKvH8m5ddEM1wIpaN3Yk6PEIEKkw2OCG8xDMs8I= IronPort-HdrOrdr: A9a23:2y1U3qi9oXjHXi8/RW5FVYLsbXBQXuIji2hC6mlwRA09TySZ// rBoB19726MtN9xYgBHpTnuAsm9qB/nmaKdpLNhWItKPzOW31dATrsSjrcKqgeIc0aVm9K1l5 0QF5SWYOeAdWSS5vya3ODXKbkdKaG8gcKVuds= X-IronPort-AV: E=Sophos;i="5.95,214,1661832000"; d="scan'208";a="83149672" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Xen Security Team , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Wei Liu , Stefano Stabellini , Julien Grall , Volodymyr Babchuk , "Bertrand Marquis" , Henry Wang , "Anthony PERARD" Subject: [PATCH 3/4] xen/arm, libxl: Revert XEN_DOMCTL_shadow_op; use p2m mempool hypercalls Date: Wed, 26 Oct 2022 11:20:17 +0100 Message-ID: <20221026102018.4144-4-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20221026102018.4144-1-andrew.cooper3@citrix.com> References: <20221026102018.4144-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 This reverts most of commit cf2a68d2ffbc3ce95e01449d46180bddb10d24a0, and bits of cbea5a1149ca7fd4b7cdbfa3ec2e4f109b601ff7. First of all, with ARM borrowing x86's implementation, the logic to set the pool size should have been common, not duplicated. Introduce libxl__domain_set_p2m_pool_size() as a shared implementation, and use it from the ARM and x86 paths. It is left as an exercise to the reader to judge how libxl/xl can reasonably function without the ability to query the pool size... Remove ARM's p2m_domctl() infrastructure now the functioanlity has been replaced with a working and unit tested interface. This is part of XSA-409 / CVE-2022-33747. Signed-off-by: Andrew Cooper --- CC: Xen Security Team CC: Jan Beulich CC: Roger Pau Monné CC: Wei Liu CC: Stefano Stabellini CC: Julien Grall CC: Volodymyr Babchuk CC: Bertrand Marquis CC: Henry Wang CC: Anthony PERARD --- tools/libs/light/libxl_arm.c | 14 +---------- tools/libs/light/libxl_dom.c | 19 ++++++++++++++ tools/libs/light/libxl_internal.h | 3 +++ tools/libs/light/libxl_x86.c | 15 ++--------- xen/arch/arm/domctl.c | 53 --------------------------------------- xen/arch/arm/include/asm/p2m.h | 1 - xen/arch/arm/p2m.c | 8 ------ 7 files changed, 25 insertions(+), 88 deletions(-) diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index 2a5e93c28403..2f5615263543 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -209,19 +209,7 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl__domain_build_state *state, uint32_t domid) { - libxl_ctx *ctx = libxl__gc_owner(gc); - unsigned int shadow_mb = DIV_ROUNDUP(d_config->b_info.shadow_memkb, 1024); - - int r = xc_shadow_control(ctx->xch, domid, - XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION, - &shadow_mb, 0); - if (r) { - LOGED(ERROR, domid, - "Failed to set %u MiB shadow allocation", shadow_mb); - return ERROR_FAIL; - } - - return 0; + return libxl__domain_set_p2m_pool_size(gc, d_config, domid); } int libxl__arch_extra_memory(libxl__gc *gc, diff --git a/tools/libs/light/libxl_dom.c b/tools/libs/light/libxl_dom.c index 2abaab439c4f..f93b221f1c1f 100644 --- a/tools/libs/light/libxl_dom.c +++ b/tools/libs/light/libxl_dom.c @@ -1448,6 +1448,25 @@ int libxl_userdata_unlink(libxl_ctx *ctx, uint32_t domid, return rc; } +int libxl__domain_set_p2m_pool_size( + libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + uint64_t shadow_mem; + + shadow_mem = d_config->b_info.shadow_memkb; + shadow_mem <<= 10; + + int r = xc_get_p2m_mempool_size(ctx->xch, domid, &shadow_mem); + if (r) { + LOGED(ERROR, domid, + "Failed to set p2m pool size to %"PRIu64"kB", shadow_mem); + return ERROR_FAIL; + } + + return 0; +} + /* * Local variables: * mode: C diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h index cb9e8b3b8b5a..f31164bc6c0d 100644 --- a/tools/libs/light/libxl_internal.h +++ b/tools/libs/light/libxl_internal.h @@ -4864,6 +4864,9 @@ int libxl__is_domid_recent(libxl__gc *gc, uint32_t domid, bool *recent); /* os-specific implementation of setresuid() */ int libxl__setresuid(uid_t ruid, uid_t euid, uid_t suid); +_hidden int libxl__domain_set_p2m_pool_size( + libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid); + #endif /* diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c index 7c5ee74443e5..99aba51d05df 100644 --- a/tools/libs/light/libxl_x86.c +++ b/tools/libs/light/libxl_x86.c @@ -538,20 +538,9 @@ int libxl__arch_domain_create(libxl__gc *gc, xc_domain_set_time_offset(ctx->xch, domid, rtc_timeoffset); if (d_config->b_info.type != LIBXL_DOMAIN_TYPE_PV) { - unsigned int shadow_mb = DIV_ROUNDUP(d_config->b_info.shadow_memkb, - 1024); - int r = xc_shadow_control(ctx->xch, domid, - XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION, - &shadow_mb, 0); - - if (r) { - LOGED(ERROR, domid, - "Failed to set %u MiB %s allocation", - shadow_mb, - libxl_defbool_val(d_config->c_info.hap) ? "HAP" : "shadow"); - ret = ERROR_FAIL; + ret = libxl__domain_set_p2m_pool_size(gc, d_config, domid); + if (ret) goto out; - } } if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c index c8fdeb124084..1baf25c3d98b 100644 --- a/xen/arch/arm/domctl.c +++ b/xen/arch/arm/domctl.c @@ -47,64 +47,11 @@ static int handle_vuart_init(struct domain *d, return rc; } -static long p2m_domctl(struct domain *d, struct xen_domctl_shadow_op *sc, - XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) -{ - long rc; - bool preempted = false; - - if ( unlikely(d == current->domain) ) - { - printk(XENLOG_ERR "Tried to do a p2m domctl op on itself.\n"); - return -EINVAL; - } - - if ( unlikely(d->is_dying) ) - { - printk(XENLOG_ERR "Tried to do a p2m domctl op on dying domain %u\n", - d->domain_id); - return -EINVAL; - } - - switch ( sc->op ) - { - case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: - { - /* Allow and handle preemption */ - spin_lock(&d->arch.paging.lock); - rc = p2m_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted); - spin_unlock(&d->arch.paging.lock); - - if ( preempted ) - /* Not finished. Set up to re-run the call. */ - rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h", - u_domctl); - else - /* Finished. Return the new allocation. */ - sc->mb = p2m_get_allocation(d); - - return rc; - } - case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: - { - sc->mb = p2m_get_allocation(d); - return 0; - } - default: - { - printk(XENLOG_ERR "Bad p2m domctl op %u\n", sc->op); - return -EINVAL; - } - } -} - long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { switch ( domctl->cmd ) { - case XEN_DOMCTL_shadow_op: - return p2m_domctl(d, &domctl->u.shadow_op, u_domctl); case XEN_DOMCTL_cacheflush: { gfn_t s = _gfn(domctl->u.cacheflush.start_pfn); diff --git a/xen/arch/arm/include/asm/p2m.h b/xen/arch/arm/include/asm/p2m.h index c8f14d13c2c5..91df922e1c9f 100644 --- a/xen/arch/arm/include/asm/p2m.h +++ b/xen/arch/arm/include/asm/p2m.h @@ -222,7 +222,6 @@ void p2m_restore_state(struct vcpu *n); /* Print debugging/statistial info about a domain's p2m */ void p2m_dump_info(struct domain *d); -unsigned int p2m_get_allocation(struct domain *d); int p2m_set_allocation(struct domain *d, unsigned long pages, bool *preempted); int p2m_teardown_allocation(struct domain *d); diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 4607cde6f0b8..92b678cf0d09 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -92,14 +92,6 @@ static void p2m_free_page(struct domain *d, struct page_info *pg) spin_unlock(&d->arch.paging.lock); } -/* Return the size of the pool, rounded up to the nearest MB */ -unsigned int p2m_get_allocation(struct domain *d) -{ - unsigned long nr_pages = ACCESS_ONCE(d->arch.paging.p2m_total_pages); - - return ROUNDUP(nr_pages, 1 << (20 - PAGE_SHIFT)) >> (20 - PAGE_SHIFT); -} - /* Return the size of the pool, in bytes. */ int arch_get_p2m_mempool_size(struct domain *d, uint64_t *size) { From patchwork Wed Oct 26 10:20:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13020437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DD627C433FE for ; Wed, 26 Oct 2022 10:21:04 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.430426.682144 (Exim 4.92) (envelope-from ) id 1ondWr-0006WB-QB; Wed, 26 Oct 2022 10:20:57 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 430426.682144; Wed, 26 Oct 2022 10:20:57 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWr-0006W4-Mq; Wed, 26 Oct 2022 10:20:57 +0000 Received: by outflank-mailman (input) for mailman id 430426; Wed, 26 Oct 2022 10:20:56 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ondWq-0004c6-EW for xen-devel@lists.xenproject.org; Wed, 26 Oct 2022 10:20:56 +0000 Received: from esa6.hc3370-68.iphmx.com (esa6.hc3370-68.iphmx.com [216.71.155.175]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id e0276613-5517-11ed-91b5-6bf2151ebd3b; Wed, 26 Oct 2022 12:20:55 +0200 (CEST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e0276613-5517-11ed-91b5-6bf2151ebd3b DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1666779655; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=t5KooTTb63GFPiYoUuuSBv6eBVEQmvOiWx0QPIN98xg=; b=DIPP8RbpyuAdb8a800d1bbpOHvVoEFfreEv7uGA7b+wDR3TMQhHtH4Ng IPTHrqiR1nhZpvt58IwrzRtk7BstTMGrKkr9Q/y3N4Sym1x8orZYGFt4L CtdC1ivOTZONq3LXixZEePa9PpJoBU/SlT7ExDgK0GhQQc4bSZNPxT/TZ A=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none X-SBRS: 5.1 X-MesageID: 83149673 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-Data: A9a23:3OoMwa0wGqWOlsj0/vbD5UNxkn2cJEfYwER7XKvMYLTBsI5bpzcGy WUeXmiPO6mCYGXwc91yaoS3/UJS75KGx9FjSQRtpC1hF35El5HIVI+TRqvS04F+DeWYFR46s J9OAjXkBJppJpMJjk71atANlVEliefSAOKU5NfsYkhZXRVjRDoqlSVtkus4hp8AqdWiCkaGt MiaT/f3YTdJ4BYpdDNJg06/gEk35q6r4GlG5gVWic1j5zcyqVFEVPrzGonpR5fIatE8NvK3Q e/F0Ia48gvxl/v6Ior4+lpTWhRiro/6ZWBiuFIPM0SRqkEqShgJ+rQ6LJIhhXJ/0F1lqTzTJ OJl7vRcQS9xVkHFdX90vxNwS0mSNoUekFPLzOTWXWV+ACQqflO1q8iCAn3aMqUVyr1tOToQz 8caOSEvTUyEuN3v5LCkH7wEasQLdKEHPasas3BkizrYEewnUdbIRKCiCd1whWlqwJoURLCHO pRfOWEHgBfoOnWjPn8+Dp4kkfjurX74azBC83qepLYt4niVxwt0uFToGIqOI4DbG5oO9qqej lmd8VjUHBQ2CMeWkQu+1k/2usCSlzyuDer+E5Xnr6U30TV/3Fc7NhoSUleqpOijvWS3UdlfN k889zInqO4580nDZtvgWxy1plaUsxhaXMBfe8Ua5QeX2+zr6gCWLmEeS3hKb9lOnMU7XyAw3 1mF2dbgHyVysaa9QGiYsLyTqFuaIjMJJGUPYSsFSwot4NT5pow3yBXVQb5LC6O+k8f0BSDY0 z2M6i8kiN07ncMNkqm2413DqzatvYTSCB444B3NWWCo5R8/Y5SqD6S37XDL4PAGK5yWJnGjl nUZn8mV7MgVEIqA0ieKRY0w8KqBvqjfdmeG2Bg2Qsdnp2/FF2OfkZ547QElPn8ybPw/ey74Q myPvjxuvbtRIy7/BUNoWL6ZB8MvxKnmMN3qUPHIc9ZDCqRMmB+7EDJGPhDJgT20+KQ4ueRmY MrAL57wZZoPIf4/pAdaUdvxxlPCKsoW4WrIDa72wB28uVZ1TC7EEOxVWLdigw1Q0U9lnOk32 4wBXydp408FOAEbXsUw2ddKRW3m1VBhWfjLRzV/L4Zv2DZOFmA7EOP2yrg8YYFjlKk9vr6Wo C/iABUJkQOl3SCvxeC2hpdLMe2HYHqChShjYXxE0aiAhxDPnrpDHI9ALsBqLNHLBcRozOJuT ultRilzKq0nd9gzwBxENcOVhNU7LHyD3FveVxdJlRBiJvaMsSSSoYS6FuYunQFTZheKWTwW+ eb5h16FHMdSL+mgZe6PAM+SI5qKlSB1sIpPs4HgebG/pG2EHFBWFhHM IronPort-HdrOrdr: A9a23:V8FBpqGjbxka7YOKpLqE7seALOsnbusQ8zAXP0AYc3Nom6uj5q aTdZUgpHjJYVkqOU3I9ersBEDEewK/yXcX2/h0AV7BZmnbUQKTRekIh7cKgQeQfhEWntQtrJ uIGJIRNDSfNzRHZL7BkWqFL+o= X-IronPort-AV: E=Sophos;i="5.95,214,1661832000"; d="scan'208";a="83149673" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Xen Security Team , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Wei Liu , Stefano Stabellini , Julien Grall , Volodymyr Babchuk , "Bertrand Marquis" , Henry Wang , "Anthony PERARD" Subject: [PATCH 4/4] xen/arm: Correct the p2m pool size calculations Date: Wed, 26 Oct 2022 11:20:18 +0100 Message-ID: <20221026102018.4144-5-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20221026102018.4144-1-andrew.cooper3@citrix.com> References: <20221026102018.4144-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Allocating or freeing p2m pages doesn't alter the size of the mempool; only the split between free and used pages. Right now, the hypercalls operate on the free subset of the pool, meaning that XEN_DOMCTL_get_p2m_mempool_size varies with time as the guest shuffles its physmap, and XEN_DOMCTL_set_p2m_mempool_size ignores the used subset of the pool and lets the guest grow unbounded. This fixes test-p2m-pool on ARM so that the behaviour matches x86. This is part of XSA-409 / CVE-2022-33747. Fixes: cbea5a1149ca ("xen/arm: Allocate and free P2M pages from the P2M pool") Signed-off-by: Andrew Cooper Reviewed-by: Julien Grall --- CC: Xen Security Team CC: Jan Beulich CC: Roger Pau Monné CC: Wei Liu CC: Stefano Stabellini CC: Julien Grall CC: Volodymyr Babchuk CC: Bertrand Marquis CC: Henry Wang CC: Anthony PERARD --- xen/arch/arm/p2m.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 92b678cf0d09..dd9696c48312 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -72,7 +72,6 @@ static struct page_info *p2m_alloc_page(struct domain *d) spin_unlock(&d->arch.paging.lock); return NULL; } - d->arch.paging.p2m_total_pages--; } spin_unlock(&d->arch.paging.lock); @@ -85,10 +84,7 @@ static void p2m_free_page(struct domain *d, struct page_info *pg) if ( is_hardware_domain(d) ) free_domheap_page(pg); else - { - d->arch.paging.p2m_total_pages++; page_list_add_tail(pg, &d->arch.paging.p2m_freelist); - } spin_unlock(&d->arch.paging.lock); }