From patchwork Tue Feb 25 09:53:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11403163 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 005D014D5 for ; Tue, 25 Feb 2020 09:55:44 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id C5A5321744 for ; Tue, 25 Feb 2020 09:55:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="B6xFmxhk" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C5A5321744 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1j6Wv6-0005v2-Sx; Tue, 25 Feb 2020 09:54:28 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1j6Wv5-0005ub-8i for xen-devel@lists.xenproject.org; Tue, 25 Feb 2020 09:54:27 +0000 X-Inumbo-ID: c75dd4d6-57b4-11ea-a490-bc764e2007e4 Received: from smtp-fw-9102.amazon.com (unknown [207.171.184.29]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id c75dd4d6-57b4-11ea-a490-bc764e2007e4; Tue, 25 Feb 2020 09:54:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1582624455; x=1614160455; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZGnO7Sr7uKlEAQb3ApRus6MhV+natOlVsHlToI8RNeA=; b=B6xFmxhkuwdvJ25dIe2QI3j4O708oVSSlBd3u+gG1AlaviXvCycmrvtX cWUcY4Aa42LXteEuH2fmlpLl0HtP1mCINbqot/Ry8yY20lHsKcmGJIhjN 8h2ETdRHgahAo5mODaxHYiV3ajWkR/um4lvF0/96AV2gq16juetBXl/Ou I=; IronPort-SDR: 6m/2IL2yk44Hoi0gcpLG5cALC1ml63v01irv6ItU450hZZHCtVUE2FdPTbdKTWP6A7t47pW/Bj gxCVt9iVyABA== X-IronPort-AV: E=Sophos;i="5.70,483,1574121600"; d="scan'208";a="27308305" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-2b-81e76b79.us-west-2.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-9102.sea19.amazon.com with ESMTP; 25 Feb 2020 09:54:13 +0000 Received: from EX13MTAUEA002.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan3.pdx.amazon.com [10.170.41.166]) by email-inbound-relay-2b-81e76b79.us-west-2.amazon.com (Postfix) with ESMTPS id 42255A254A; Tue, 25 Feb 2020 09:54:11 +0000 (UTC) Received: from EX13D32EUB001.ant.amazon.com (10.43.166.125) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Tue, 25 Feb 2020 09:54:10 +0000 Received: from EX13MTAUWA001.ant.amazon.com (10.43.160.58) by EX13D32EUB001.ant.amazon.com (10.43.166.125) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 25 Feb 2020 09:54:09 +0000 Received: from u2f063a87eabd5f.cbg10.amazon.com (10.125.106.135) by mail-relay.amazon.com (10.43.160.118) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Tue, 25 Feb 2020 09:54:06 +0000 From: Paul Durrant To: Date: Tue, 25 Feb 2020 09:53:57 +0000 Message-ID: <20200225095357.3923-3-pdurrant@amazon.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225095357.3923-1-pdurrant@amazon.com> References: <20200225095357.3923-1-pdurrant@amazon.com> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH 2/2] domain: use PGC_extra domheap page for shared_info X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Julien Grall , Wei Liu , Konrad Rzeszutek Wilk , Andrew Cooper , Paul Durrant , Ian Jackson , George Dunlap , Jan Beulich , Volodymyr Babchuk Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" There's no particular reason shared_info need use a xenheap page. It's only purpose is to be mapped by the guest so use a PGC_extra domheap page instead. This does entail freeing shared_info during domain_relinquish_resources() rather than domain_destroy() so care is needed to avoid de-referencing a NULL shared_info pointer hence some extra checks of 'is_dying' are needed. ASSERTions are added before apparently vulnerable dereferences in the event channel code. These should not be hit because domain_kill() calls evtchn_destroy() before calling domain_relinquish_resources() but are added to catch any future re-ordering. For Arm, the call to free_shared_info() in arch_domain_destroy() is left in place since it called in the error path for arch_domain_create(). NOTE: A modification in p2m_alloc_table() is required to avoid a false positive when checking for domain memory. A fix is also needed in dom0_construct_pv() to avoid automatically adding PGC_extra pages to the physmap. Signed-off-by: Paul Durrant --- Cc: Stefano Stabellini Cc: Julien Grall Cc: Volodymyr Babchuk Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Cc: Wei Liu --- xen/arch/arm/domain.c | 2 ++ xen/arch/x86/domain.c | 3 ++- xen/arch/x86/mm/p2m.c | 3 +-- xen/arch/x86/pv/dom0_build.c | 4 ++++ xen/common/domain.c | 25 +++++++++++++++++++------ xen/common/event_2l.c | 4 ++++ xen/common/event_fifo.c | 1 + xen/common/time.c | 3 +++ 8 files changed, 36 insertions(+), 9 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 2cbcdaac08..3904519256 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -1006,6 +1006,8 @@ int domain_relinquish_resources(struct domain *d) BUG(); } + free_shared_info(d); + return 0; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index eb7b0fc51c..3ad532eccf 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -691,7 +691,6 @@ void arch_domain_destroy(struct domain *d) pv_domain_destroy(d); free_perdomain_mappings(d); - free_shared_info(d); cleanup_domain_irq_mapping(d); psr_domain_free(d); @@ -2246,6 +2245,8 @@ int domain_relinquish_resources(struct domain *d) if ( is_hvm_domain(d) ) hvm_domain_relinquish_resources(d); + free_shared_info(d); + return 0; } diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index c5f428d67c..787d97d85e 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -695,8 +695,7 @@ int p2m_alloc_table(struct p2m_domain *p2m) p2m_lock(p2m); - if ( p2m_is_hostp2m(p2m) - && !page_list_empty(&d->page_list) ) + if ( p2m_is_hostp2m(p2m) && domain_tot_pages(d) ) { P2M_ERROR("dom %d already has memory allocated\n", d->domain_id); p2m_unlock(p2m); diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c index dc16ef2e79..f8f1bbe2f4 100644 --- a/xen/arch/x86/pv/dom0_build.c +++ b/xen/arch/x86/pv/dom0_build.c @@ -792,6 +792,10 @@ int __init dom0_construct_pv(struct domain *d, { mfn = mfn_x(page_to_mfn(page)); BUG_ON(SHARED_M2P(get_gpfn_from_mfn(mfn))); + + if ( page->count_info & PGC_extra ) + continue; + if ( get_gpfn_from_mfn(mfn) >= count ) { BUG_ON(is_pv_32bit_domain(d)); diff --git a/xen/common/domain.c b/xen/common/domain.c index ba7a905258..1d42fbcc0f 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -128,9 +128,9 @@ static void vcpu_info_reset(struct vcpu *v) { struct domain *d = v->domain; - v->vcpu_info = ((v->vcpu_id < XEN_LEGACY_MAX_VCPUS) + v->vcpu_info = (!d->is_dying && v->vcpu_id < XEN_LEGACY_MAX_VCPUS) ? (vcpu_info_t *)&shared_info(d, vcpu_info[v->vcpu_id]) - : &dummy_vcpu_info); + : &dummy_vcpu_info; v->vcpu_info_mfn = INVALID_MFN; } @@ -1650,24 +1650,37 @@ int continue_hypercall_on_cpu( int alloc_shared_info(struct domain *d, unsigned int memflags) { - if ( (d->shared_info.virt = alloc_xenheap_pages(0, memflags)) == NULL ) + struct page_info *pg; + + pg = alloc_domheap_page(d, MEMF_no_refcount | memflags); + if ( !pg ) return -ENOMEM; - d->shared_info.mfn = virt_to_mfn(d->shared_info.virt); + if ( !get_page_and_type(pg, d, PGT_writable_page) ) + return -ENODATA; + + d->shared_info.mfn = page_to_mfn(pg); + d->shared_info.virt = __map_domain_page_global(pg); clear_page(d->shared_info.virt); - share_xen_page_with_guest(mfn_to_page(d->shared_info.mfn), d, SHARE_rw); return 0; } void free_shared_info(struct domain *d) { + struct page_info *pg; + if ( !d->shared_info.virt ) return; - free_xenheap_page(d->shared_info.virt); + unmap_domain_page_global(d->shared_info.virt); d->shared_info.virt = NULL; + + pg = mfn_to_page(d->shared_info.mfn); + + put_page_alloc_ref(pg); + put_page_and_type(pg); } /* diff --git a/xen/common/event_2l.c b/xen/common/event_2l.c index e1dbb860f4..a72fe0232b 100644 --- a/xen/common/event_2l.c +++ b/xen/common/event_2l.c @@ -27,6 +27,7 @@ static void evtchn_2l_set_pending(struct vcpu *v, struct evtchn *evtchn) * others may require explicit memory barriers. */ + ASSERT(d->shared_info.virt); if ( guest_test_and_set_bit(d, port, &shared_info(d, evtchn_pending)) ) return; @@ -54,6 +55,7 @@ static void evtchn_2l_unmask(struct domain *d, struct evtchn *evtchn) * These operations must happen in strict order. Based on * evtchn_2l_set_pending() above. */ + ASSERT(d->shared_info.virt); if ( guest_test_and_clear_bit(d, port, &shared_info(d, evtchn_mask)) && guest_test_bit(d, port, &shared_info(d, evtchn_pending)) && !guest_test_and_set_bit(d, port / BITS_PER_EVTCHN_WORD(d), @@ -67,6 +69,7 @@ static bool evtchn_2l_is_pending(const struct domain *d, evtchn_port_t port) { unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d); + ASSERT(d->shared_info.virt); ASSERT(port < max_ports); return (port < max_ports && guest_test_bit(d, port, &shared_info(d, evtchn_pending))); @@ -76,6 +79,7 @@ static bool evtchn_2l_is_masked(const struct domain *d, evtchn_port_t port) { unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d); + ASSERT(d->shared_info.virt); ASSERT(port < max_ports); return (port >= max_ports || guest_test_bit(d, port, &shared_info(d, evtchn_mask))); diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c index 230f440f14..e8c6045d72 100644 --- a/xen/common/event_fifo.c +++ b/xen/common/event_fifo.c @@ -497,6 +497,7 @@ static void setup_ports(struct domain *d) evtchn = evtchn_from_port(d, port); + ASSERT(d->shared_info.virt); if ( guest_test_bit(d, port, &shared_info(d, evtchn_pending)) ) evtchn->pending = 1; diff --git a/xen/common/time.c b/xen/common/time.c index 58fa9abc40..938226c7b1 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -99,6 +99,9 @@ void update_domain_wallclock_time(struct domain *d) uint32_t *wc_version; uint64_t sec; + if ( d->is_dying ) + return; + spin_lock(&wc_lock); wc_version = &shared_info(d, wc_version);