[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] xen/arm: p2m: Free the p2m entry after flushing the IOMMU TLBs



+ Juergen

On Mon, 12 Aug 2019, Julien Grall wrote:
> When freeing a p2m entry, all the sub-tree behind it will also be freed.
> This may include intermediate page-tables or any l3 entry requiring to
> drop a reference (e.g for foreign pages). As soon as pages are freed,
> they may be re-used by Xen or another domain. Therefore it is necessary
> to flush *all* the TLBs beforehand.
> 
> While CPU TLBs will be flushed before freeing the pages, this is not
> the case for IOMMU TLBs. This can be solved by moving the IOMMU TLBs
> flush earlier in the code.
> 
> This wasn't considered as a security issue as device passthrough on Arm
> is not security supported.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxx>

Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>


> ---
> 
> Cc: olekstysh@xxxxxxxxx
> Cc: oleksandr_tyshchenko@xxxxxxxx
> 
>     I discovered it while looking at the code, so I don't have any
>     reproducer of the issue. There is a small windows where page could
>     be reallocated to Xen or another domain but still present in the
>     IOMMU TLBs.
> 
>     This patch only address the case where the flush succeed. In the
>     unlikely case where it does not succeed, then we will still free the
>     pages. The IOMMU helper will crash domain, but the device may still
>     not be quiescent. So there are a potentially issues do DMA on wrong
>     things.
> 
>     At the moment, none of the Arm IOMMUs drivers (including the IPMMU
>     one under review) are return an error here. Note that flush may
>     still fail (see timeout), but is ignored. This is not great as it
>     means a device may DMA into something that does not belong to the
>     domain. So we probably want to return an error here.
> 
>     Even if an error is returned, there are still potential issues
>     (see above). The fix is not entirely trivial, we would need to keep
>     the page around until the a device is quiescent or the IOMMU is
>     reset. This mostly likely means until the domain is fully destroyed.
> 
>     One of the solution would be to:
>        1) Have a pool of memory for each domain p2m page-tables. So the
>        domain can only touch itself
>        2) Defer foreign mapping removal
> 
>     1) should also solve the case where the P2M is trying to shatter
>     everything and therefore hog the memory. Note that today we don't
>     free empty page-tables.
> 
>     2) I always felt trying to remove the foreign page reference in the
>     p2m code was wrong. This is done because we currently allow the
>     guest to remove any mapping. So we need to protect ourself against a
>     rogue guest. We could try to restrict what the guest can do on the
>     p2m.
> ---
>  xen/arch/arm/p2m.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 3c8287a048..963cd1d600 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1048,14 +1048,6 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
>          p2m->lowest_mapped_gfn = gfn_min(p2m->lowest_mapped_gfn, sgfn);
>      }
>  
> -    /*
> -     * Free the entry only if the original pte was valid and the base
> -     * is different (to avoid freeing when permission is changed).
> -     */
> -    if ( p2m_is_valid(orig_pte) &&
> -         !mfn_eq(lpae_get_mfn(*entry), lpae_get_mfn(orig_pte)) )
> -        p2m_free_entry(p2m, orig_pte, level);
> -
>      if ( has_iommu_pt(p2m->domain) &&
>           (lpae_is_valid(orig_pte) || lpae_is_valid(*entry)) )
>      {
> @@ -1072,6 +1064,14 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
>      else
>          rc = 0;
>  
> +    /*
> +     * Free the entry only if the original pte was valid and the base
> +     * is different (to avoid freeing when permission is changed).
> +     */
> +    if ( p2m_is_valid(orig_pte) &&
> +         !mfn_eq(lpae_get_mfn(*entry), lpae_get_mfn(orig_pte)) )
> +        p2m_free_entry(p2m, orig_pte, level);
> +
>  out:
>      unmap_domain_page(table);
>  
> -- 
> 2.11.0
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.