mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/gnttab: Prevent GNTTABOP_cache_flush from corrupting RO grants
Grants can be offered read-only by the owning domain. While a domain mapping
a RO grant may have a need to invalidate the cache, it must not modify the
other-guests data while doing so. Force-upgrade to a clean operation in this
case.
This is CVE-2026-102702, part of XSA-519.
Fixes: 18e8d22fe7 ("introduce GNTTABOP_cache_flush")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
4b8a11b421
commit
c89185286c
1 file changed
+26
-1
@@ -983,6 +983,13 @@ static struct active_grant_entry *grant_map_exists(const struct domain *ld,
|
|||||||
|
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool grant_map_is_ro(struct active_grant_entry *act)
|
||||||
|
{
|
||||||
|
ASSERT(spin_is_locked(&act->lock));
|
||||||
|
|
||||||
|
return (act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) == 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_HAS_GRANT_CACHE_FLUSH */
|
#endif /* CONFIG_HAS_GRANT_CACHE_FLUSH */
|
||||||
|
|
||||||
union maptrack_node {
|
union maptrack_node {
|
||||||
@@ -3597,7 +3604,7 @@ gnttab_swap_grant_ref(XEN_GUEST_HANDLE_PARAM(gnttab_swap_grant_ref_t) uop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HAS_GRANT_CACHE_FLUSH
|
#ifdef CONFIG_HAS_GRANT_CACHE_FLUSH
|
||||||
static int _cache_flush(const gnttab_cache_flush_t *cflush, grant_ref_t *cur_ref)
|
static int _cache_flush(gnttab_cache_flush_t *cflush, grant_ref_t *cur_ref)
|
||||||
{
|
{
|
||||||
struct domain *d, *owner;
|
struct domain *d, *owner;
|
||||||
struct page_info *page;
|
struct page_info *page;
|
||||||
@@ -3648,6 +3655,24 @@ static int _cache_flush(const gnttab_cache_flush_t *cflush, grant_ref_t *cur_ref
|
|||||||
put_page(page);
|
put_page(page);
|
||||||
return act ? PTR_ERR(act) : 1;
|
return act ? PTR_ERR(act) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the grant mapping is read-only, it must be cleaned as well as
|
||||||
|
* invalidated. Invalidation without cleaning may modify memory the
|
||||||
|
* granter is expecting not to change.
|
||||||
|
*
|
||||||
|
* It is highly unlikely but legal to have multiple grant mappings of
|
||||||
|
* differing read-only-ness. If a read-write grant mapping is found
|
||||||
|
* first, then it's fine to invalidate without clean.
|
||||||
|
*
|
||||||
|
* If a read-only grant mapping is found first, a later read-write
|
||||||
|
* mapping could be missed. Assume that the read-only mapping is the
|
||||||
|
* only mapping. The cost is a clean of up to 4k, while the saving is
|
||||||
|
* not requiring the search of grant maps to be exhaustive in order to
|
||||||
|
* spot a corner-case expected not to exist in practice.
|
||||||
|
*/
|
||||||
|
if ( grant_map_is_ro(act) )
|
||||||
|
cflush->op |= GNTTAB_CACHE_CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = map_domain_page(mfn);
|
v = map_domain_page(mfn);
|
||||||
|
|||||||