From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2] x86/mm: also flush TLB when putting writable foreign page reference Date: Tue, 25 Apr 2017 02:59:18 -0600 Message-ID: <58FF2C060200007800153D45@prv-mh.provo.novell.com> References: <58FF2C060200007800153D45@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part360F9CF6.3__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d2wJh-0007jL-82 for xen-devel@lists.xenproject.org; Tue, 25 Apr 2017 08:59:25 +0000 List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Andrew Cooper , Julien Grall , Jann Horn List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part360F9CF6.3__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Jann's explanation of the problem: "start situation: - domain A and domain B are PV domains - domain A and B both have currently scheduled vCPUs, and the vCPUs are not scheduled away - domain A has XSM_TARGET access to domain B - page X is owned by domain B and has no mappings - page X is zeroed steps: - domain A uses do_mmu_update() to map page X in domain A as writable - domain A accesses page X through the new PTE, creating a TLB entry - domain A removes its mapping of page X - type count of page X goes to 0 - tlbflush_timestamp of page X is bumped - domain B maps page X as L1 pagetable - type of page X changes to PGT_l1_page_table - TLB flush is forced using domain_dirty_cpumask of domain B - page X is mapped as L1 pagetable in domain B At this point, domain B's vCPUs are guaranteed to have no incorrectly-typed stale TLB entries for page X, but AFAICS domain A's vCPUs can still have stale TLB entries that map page X as writable, permitting domain A to control a live pagetable of domain B." Domain A necessarily is Dom0 (DomU-s with XSM_TARGET permission are being created only for HVM domains, but domain B needs to be PV here), so this is not a security issue, but nevertheless seems desirable to correct. Reported-by: Jann Horn Signed-off-by: Jan Beulich --- v2: Don't consider page's time stamp (relevant only for the owning domain). --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1266,6 +1266,18 @@ void put_page_from_l1e(l1_pgentry_t l1e, if ( (l1e_get_flags(l1e) & _PAGE_RW) &&=20 ((l1e_owner =3D=3D pg_owner) || !paging_mode_external(pg_owner)) = ) { + /* + * Don't leave stale writable TLB entries in the unmapping = domain's + * page tables, to prevent them allowing access to pages required = to + * be read-only (e.g. after pg_owner changed them to page table = or + * segment descriptor pages). + */ + if ( unlikely(l1e_owner !=3D pg_owner) ) + { + perfc_incr(need_flush_tlb_flush); + flush_tlb_mask(l1e_owner->domain_dirty_cpumask); + } + put_page_and_type(page); } else --=__Part360F9CF6.3__= Content-Type: text/plain; name="x86-put-l1e-foreign-flush.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-put-l1e-foreign-flush.patch" x86/mm: also flush TLB when putting writable foreign page reference=0A=0AJa= nn's explanation of the problem:=0A=0A"start situation:=0A - domain A and = domain B are PV domains=0A - domain A and B both have currently scheduled = vCPUs, and the vCPUs=0A are not scheduled away=0A - domain A has = XSM_TARGET access to domain B=0A - page X is owned by domain B and has no = mappings=0A - page X is zeroed=0A=0A steps:=0A - domain A uses do_mmu_updat= e() to map page X in domain A as writable=0A - domain A accesses page X = through the new PTE, creating a TLB entry=0A - domain A removes its = mapping of page X=0A - type count of page X goes to 0=0A - tlbflush_tim= estamp of page X is bumped=0A - domain B maps page X as L1 pagetable=0A = - type of page X changes to PGT_l1_page_table=0A - TLB flush is forced = using domain_dirty_cpumask of domain B=0A - page X is mapped as L1 = pagetable in domain B=0A=0A At this point, domain B's vCPUs are guaranteed = to have no=0A incorrectly-typed stale TLB entries for page X, but AFAICS = domain A's=0A vCPUs can still have stale TLB entries that map page X as = writable,=0A permitting domain A to control a live pagetable of domain = B."=0A=0ADomain A necessarily is Dom0 (DomU-s with XSM_TARGET permission = are=0Abeing created only for HVM domains, but domain B needs to be PV = here),=0Aso this is not a security issue, but nevertheless seems desirable = to=0Acorrect.=0A=0AReported-by: Jann Horn =0ASigned-off-b= y: Jan Beulich =0A---=0Av2: Don't consider page's time = stamp (relevant only for the owning=0A domain).=0A=0A--- a/xen/arch/x86/= mm.c=0A+++ b/xen/arch/x86/mm.c=0A@@ -1266,6 +1266,18 @@ void put_page_from_= l1e(l1_pgentry_t l1e,=0A if ( (l1e_get_flags(l1e) & _PAGE_RW) && =0A = ((l1e_owner =3D=3D pg_owner) || !paging_mode_external(pg_owner)) = )=0A {=0A+ /*=0A+ * Don't leave stale writable TLB = entries in the unmapping domain's=0A+ * page tables, to prevent = them allowing access to pages required to=0A+ * be read-only (e.g. = after pg_owner changed them to page table or=0A+ * segment = descriptor pages).=0A+ */=0A+ if ( unlikely(l1e_owner !=3D = pg_owner) )=0A+ {=0A+ perfc_incr(need_flush_tlb_flush);= =0A+ flush_tlb_mask(l1e_owner->domain_dirty_cpumask);=0A+ = }=0A+=0A put_page_and_type(page);=0A }=0A else=0A --=__Part360F9CF6.3__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part360F9CF6.3__=--