-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoWuZBM6M3lCBSfTnuARItAMU6BMFAmRT4cIACgkQuARItAMU
 6BPZ6xAA0T0AhPUuc4JyKH4p2ZFaH61+1YpGHlxxCyIF1gm4JMHS0i1CRii+o2Zh
 k3w76MafGau9ADXwrjJAh+C+WihwwgTtSyN2/amOn70K75iK7GGbT125c6VX6A1I
 6L6lFEO/3JURrhQE4TthgH6HUVyXBC4XobQqajWtxGgcq/QRkjtgdbLPPv9HuH23
 NgXZ85+lpPrak9U0Zzu2ez1O9VIlABWbTE6B6DgcyQshwqBZDOSFRTxxJ883XtqH
 7sRMmVJBkiF3HRqvDAmxI0eUOrR8YNtl1PN441iadmvfqG4IDbPtuJ0UtiyNagXT
 g7UYGvv7Qj2z4y2QhQSgLiIC0Zrl/T6Vw/7oXt0CVybhEMuAAeshWzHIl5aR5aKt
 7sY2ijUX290zwuACft9ZjDspUWyOPkvqym5UrldTj1ZaYV9w7iHNezFbXTnXOBh9
 vEiet5p3SCeQNymFKXy2R+8YJ6IIsH3Mxf6SYo2CQFNNjOzfUHwKMix/uArFdXF5
 CQD6jM9NXTiPIjwpXIJjyutJ6USWZhsMCneHtItzfWTa1YnBSZTwIWU1fB05Snk/
 BcDVfJ9Pq142N983SNXaBYIGzxpYPUHYZQmKvAzbeLHcaxrgLJM9/x8zcXIxc8Wa
 sEFoo5W8DCIJRqjk7dsLyLEvPJdoBZidg6sd0MwHRGX0kDRzHEo=
 =PPnV
 -----END PGP SIGNATURE-----

Merge tag 'kvm-s390-next-6.4-2' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

For 6.4
This commit is contained in:
Paolo Bonzini 2023-05-05 06:15:09 -04:00
commit 7a8016d956
3 changed files with 23 additions and 21 deletions

View File

@ -192,21 +192,10 @@ static int expected_page_refs(struct page *page)
return res;
}
static int make_secure_pte(pte_t *ptep, unsigned long addr,
struct page *exp_page, struct uv_cb_header *uvcb)
static int make_page_secure(struct page *page, struct uv_cb_header *uvcb)
{
pte_t entry = READ_ONCE(*ptep);
struct page *page;
int expected, cc = 0;
if (!pte_present(entry))
return -ENXIO;
if (pte_val(entry) & _PAGE_INVALID)
return -ENXIO;
page = pte_page(entry);
if (page != exp_page)
return -ENXIO;
if (PageWriteback(page))
return -EAGAIN;
expected = expected_page_refs(page);
@ -304,17 +293,18 @@ int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb)
goto out;
rc = -ENXIO;
page = follow_page(vma, uaddr, FOLL_WRITE);
if (IS_ERR_OR_NULL(page))
goto out;
lock_page(page);
ptep = get_locked_pte(gmap->mm, uaddr, &ptelock);
if (should_export_before_import(uvcb, gmap->mm))
uv_convert_from_secure(page_to_phys(page));
rc = make_secure_pte(ptep, uaddr, page, uvcb);
if (pte_present(*ptep) && !(pte_val(*ptep) & _PAGE_INVALID) && pte_write(*ptep)) {
page = pte_page(*ptep);
rc = -EAGAIN;
if (trylock_page(page)) {
if (should_export_before_import(uvcb, gmap->mm))
uv_convert_from_secure(page_to_phys(page));
rc = make_page_secure(page, uvcb);
unlock_page(page);
}
}
pte_unmap_unlock(ptep, ptelock);
unlock_page(page);
out:
mmap_read_unlock(gmap->mm);

View File

@ -314,6 +314,11 @@ int kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc)
*/
if (kvm->arch.pv.set_aside)
return -EINVAL;
/* Guest with segment type ASCE, refuse to destroy asynchronously */
if ((kvm->arch.gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT)
return -EINVAL;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

View File

@ -2840,6 +2840,9 @@ EXPORT_SYMBOL_GPL(s390_unlist_old_asce);
* s390_replace_asce - Try to replace the current ASCE of a gmap with a copy
* @gmap: the gmap whose ASCE needs to be replaced
*
* If the ASCE is a SEGMENT type then this function will return -EINVAL,
* otherwise the pointers in the host_to_guest radix tree will keep pointing
* to the wrong pages, causing use-after-free and memory corruption.
* If the allocation of the new top level page table fails, the ASCE is not
* replaced.
* In any case, the old ASCE is always removed from the gmap CRST list.
@ -2854,6 +2857,10 @@ int s390_replace_asce(struct gmap *gmap)
s390_unlist_old_asce(gmap);
/* Replacing segment type ASCEs would cause serious issues */
if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT)
return -EINVAL;
page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
if (!page)
return -ENOMEM;