Skip to content

Commit 7a8016d

Browse files
committed
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
2 parents 29b38e7 + c148dc8 commit 7a8016d

3 files changed

Lines changed: 23 additions & 21 deletions

File tree

arch/s390/kernel/uv.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -192,21 +192,10 @@ static int expected_page_refs(struct page *page)
192192
return res;
193193
}
194194

195-
static int make_secure_pte(pte_t *ptep, unsigned long addr,
196-
struct page *exp_page, struct uv_cb_header *uvcb)
195+
static int make_page_secure(struct page *page, struct uv_cb_header *uvcb)
197196
{
198-
pte_t entry = READ_ONCE(*ptep);
199-
struct page *page;
200197
int expected, cc = 0;
201198

202-
if (!pte_present(entry))
203-
return -ENXIO;
204-
if (pte_val(entry) & _PAGE_INVALID)
205-
return -ENXIO;
206-
207-
page = pte_page(entry);
208-
if (page != exp_page)
209-
return -ENXIO;
210199
if (PageWriteback(page))
211200
return -EAGAIN;
212201
expected = expected_page_refs(page);
@@ -304,17 +293,18 @@ int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb)
304293
goto out;
305294

306295
rc = -ENXIO;
307-
page = follow_page(vma, uaddr, FOLL_WRITE);
308-
if (IS_ERR_OR_NULL(page))
309-
goto out;
310-
311-
lock_page(page);
312296
ptep = get_locked_pte(gmap->mm, uaddr, &ptelock);
313-
if (should_export_before_import(uvcb, gmap->mm))
314-
uv_convert_from_secure(page_to_phys(page));
315-
rc = make_secure_pte(ptep, uaddr, page, uvcb);
297+
if (pte_present(*ptep) && !(pte_val(*ptep) & _PAGE_INVALID) && pte_write(*ptep)) {
298+
page = pte_page(*ptep);
299+
rc = -EAGAIN;
300+
if (trylock_page(page)) {
301+
if (should_export_before_import(uvcb, gmap->mm))
302+
uv_convert_from_secure(page_to_phys(page));
303+
rc = make_page_secure(page, uvcb);
304+
unlock_page(page);
305+
}
306+
}
316307
pte_unmap_unlock(ptep, ptelock);
317-
unlock_page(page);
318308
out:
319309
mmap_read_unlock(gmap->mm);
320310

arch/s390/kvm/pv.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ int kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc)
314314
*/
315315
if (kvm->arch.pv.set_aside)
316316
return -EINVAL;
317+
318+
/* Guest with segment type ASCE, refuse to destroy asynchronously */
319+
if ((kvm->arch.gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT)
320+
return -EINVAL;
321+
317322
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
318323
if (!priv)
319324
return -ENOMEM;

arch/s390/mm/gmap.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,6 +2840,9 @@ EXPORT_SYMBOL_GPL(s390_unlist_old_asce);
28402840
* s390_replace_asce - Try to replace the current ASCE of a gmap with a copy
28412841
* @gmap: the gmap whose ASCE needs to be replaced
28422842
*
2843+
* If the ASCE is a SEGMENT type then this function will return -EINVAL,
2844+
* otherwise the pointers in the host_to_guest radix tree will keep pointing
2845+
* to the wrong pages, causing use-after-free and memory corruption.
28432846
* If the allocation of the new top level page table fails, the ASCE is not
28442847
* replaced.
28452848
* 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)
28542857

28552858
s390_unlist_old_asce(gmap);
28562859

2860+
/* Replacing segment type ASCEs would cause serious issues */
2861+
if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT)
2862+
return -EINVAL;
2863+
28572864
page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
28582865
if (!page)
28592866
return -ENOMEM;

0 commit comments

Comments
 (0)