[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [BUG] IOTLB is not flushed in IOMMU Unmap Process
>>> On 16.11.13 at 15:33, CHENG Yueqiang <yqcheng.2008@xxxxxxxxxxxxxxxx> wrote: > Bug Descriptions > We find that Xen does NOT flush I/O TLB when iommu_unmap_page is invoked in > PV mode. Attackers may be able to use this bug to compromise Xen. > (When a PV guest OS adds a new page into its page table, the hypervisor > should set the new page-table page read-only if the page is writable before, > and consequently flush the IOTLB to avoid DMA attacks. ) > > The following code is from __get_page_type: > if ( unlikely((x & PGT_type_mask) != type) ) > { > /* Special pages should not be accessible from devices. */ > struct domain *d = page_get_owner(page); > if ( d && !is_hvm_domain(d) && unlikely(need_iommu(d)) ) > { > if ( (x & PGT_type_mask) == PGT_writable_page ) > iommu_unmap_page(d, mfn_to_gmfn(d, page_to_mfn(page))); > else if ( type == PGT_writable_page ) > iommu_map_page(d, mfn_to_gmfn(d, page_to_mfn(page)), > page_to_mfn(page), > IOMMUF_readable|IOMMUF_writable); > } > } > > Details > When Xen deals with a L2 page table entry update, the possible function flow > is as follows: > do_mmu_update() > ->mod_l2_entry() > ->get_page_from_l2e() > ->get_page_and_type_from_pagenr > ->get_page_type() > ->__get_page_type > ->iommu_unmap_page > > ->intel_iommu_unmap_page > > ->dma_pte_clear_one() > > ->__intel_iommu_iotlb_flush > > ->iommu_flush_iotlb_psi > > ->flush_iotlb_qi > We have noticed that the function: flush_iotlb_qi is supposed to complete > the task of invalidating I/O TLB. However, it ALWAYS returns before really > flushing the IOTLB. > In flush_iotlb_qi > if ( flush_non_present_entry ) > { > if ( !cap_caching_mode(iommu->cap) ) > return 1; <-- return from this point. > else > did = 0; > } > Similarly, the function: iommu_flush_write_buffer coming next to > iommu_flush_iotlb_psi directly returns also without write buffer flushing > because the if statement: !rwbf_quirk && !cap_rwbf(iommu->cap) are also true. > Note that some internal information can be found at the end of this email, > in the log file. I agree, albeit the capability related parts are irrelevant here. > Fix Suggestions > We observe that the argument: dma_old_pte_present in the function: > __intel_iommu_iotlb_flush is always assigned as 0 in the above function flow, > the value of flush_non_present_entry in flush_iotlb_qi is always 1, the > negation of dma_old_pte_present (!dma_old_pte_present). > > We suggest to set dma_old_pte_present as 1 or collect the value from > dma_pte_present(pte). Since dma_pte_present() was checked earlier on that code path, just passing TRUE (1) here is The Right Thing To Do (TM). I'll send a patch in a minute. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |