| From 4dc5a2b7f3a845525b021e13513bcfce2bdd6d15 Mon Sep 17 00:00:00 2001 |
| From: David Hildenbrand <david@redhat.com> |
| Date: Fri, 3 Apr 2020 17:30:48 +0200 |
| Subject: [PATCH] KVM: s390: vsie: Fix possible race when shadowing region 3 |
| tables |
| |
| commit 1493e0f944f3c319d11e067c185c904d01c17ae5 upstream. |
| |
| We have to properly retry again by returning -EINVAL immediately in case |
| somebody else instantiated the table concurrently. We missed to add the |
| goto in this function only. The code now matches the other, similar |
| shadowing functions. |
| |
| We are overwriting an existing region 2 table entry. All allocated pages |
| are added to the crst_list to be freed later, so they are not lost |
| forever. However, when unshadowing the region 2 table, we wouldn't trigger |
| unshadowing of the original shadowed region 3 table that we replaced. It |
| would get unshadowed when the original region 3 table is modified. As it's |
| not connected to the page table hierarchy anymore, it's not going to get |
| used anymore. However, for a limited time, this page table will stick |
| around, so it's in some sense a temporary memory leak. |
| |
| Identified by manual code inspection. I don't think this classifies as |
| stable material. |
| |
| Fixes: 998f637cc4b9 ("s390/mm: avoid races on region/segment/page table shadowing") |
| Signed-off-by: David Hildenbrand <david@redhat.com> |
| Link: https://lore.kernel.org/r/20200403153050.20569-4-david@redhat.com |
| Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> |
| Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> |
| Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c |
| index 84b667b984bb..bc2bde4db8ae 100644 |
| --- a/arch/s390/mm/gmap.c |
| +++ b/arch/s390/mm/gmap.c |
| @@ -1844,6 +1844,7 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, |
| goto out_free; |
| } else if (*table & _REGION_ENTRY_ORIGIN) { |
| rc = -EAGAIN; /* Race with shadow */ |
| + goto out_free; |
| } |
| crst_table_init(s_r3t, _REGION3_ENTRY_EMPTY); |
| /* mark as invalid as long as the parent table is not protected */ |
| -- |
| 2.7.4 |
| |