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> (cherry picked from commitc89185286c)
This commit is contained in:
1 parent
ce69163404
commit
e6e422a9c7
1 file changed
+26
-1
@@ -968,6 +968,13 @@ static struct active_grant_entry *grant_map_exists(const struct domain *ld,
|
||||
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;
|
||||
}
|
||||
|
||||
union maptrack_node {
|
||||
struct {
|
||||
/* Radix tree slot pointers use two of the bits. */
|
||||
@@ -3527,7 +3534,7 @@ gnttab_swap_grant_ref(XEN_GUEST_HANDLE_PARAM(gnttab_swap_grant_ref_t) uop,
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 page_info *page;
|
||||
@@ -3578,6 +3585,24 @@ static int _cache_flush(const gnttab_cache_flush_t *cflush, grant_ref_t *cur_ref
|
||||
put_page(page);
|
||||
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);
|
||||
|
||||