[PATCH v2 6/8] KVM: s390: vsie: Fix unshadowing while shadowing

Claudio Imbrenda posted 8 patches 2 weeks ago
There is a newer version of this series
[PATCH v2 6/8] KVM: s390: vsie: Fix unshadowing while shadowing
Posted by Claudio Imbrenda 2 weeks ago
If shadowing causes the shadow gmap to get unshadowed, exit early to
prevent an attempt to dereference the parent pointer, which at this
point is NULL.

Opportunistically add some more checks to prevent NULL parents.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: a2c17f9270cc ("KVM: s390: New gmap code")
Fixes: e5f98a6899bd ("KVM: s390: Add some helper functions needed for vSIE")
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
---
 arch/s390/kvm/gaccess.c |  2 ++
 arch/s390/kvm/gmap.c    | 11 ++++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index dad02f7f90f1..1054f9bd107f 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -1522,6 +1522,8 @@ static int _gaccess_do_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *sg,
 				       entries[i - 1].pfn, i, entries[i - 1].writable);
 		if (rc)
 			return rc;
+		if (!sg->parent)
+			return -EAGAIN;
 	}
 
 	rc = dat_entry_walk(NULL, entries[LEVEL_MEM].gfn, sg->parent->asce, DAT_WALK_LEAF,
diff --git a/arch/s390/kvm/gmap.c b/arch/s390/kvm/gmap.c
index e9cac6dce48b..6e490735265e 100644
--- a/arch/s390/kvm/gmap.c
+++ b/arch/s390/kvm/gmap.c
@@ -1163,6 +1163,7 @@ struct gmap_protect_asce_top_level {
 static inline int __gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, struct gmap *sg,
 						struct gmap_protect_asce_top_level *context)
 {
+	struct gmap *parent;
 	int rc, i;
 
 	guard(write_lock)(&sg->kvm->mmu_lock);
@@ -1170,7 +1171,12 @@ static inline int __gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, s
 	if (kvm_s390_array_needs_retry_safe(sg->kvm, context->seq, context->f))
 		return -EAGAIN;
 
-	scoped_guard(spinlock, &sg->parent->children_lock) {
+	parent = READ_ONCE(sg->parent);
+	if (!parent)
+		return -EAGAIN;
+	scoped_guard(spinlock, &parent->children_lock) {
+		if (READ_ONCE(sg->parent) != parent)
+			return -EAGAIN;
 		for (i = 0; i < CRST_TABLE_PAGES; i++) {
 			if (!context->f[i].valid)
 				continue;
@@ -1253,6 +1259,9 @@ struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *pare
 	struct gmap *sg, *new;
 	int rc;
 
+	if (WARN_ON(!parent))
+		return ERR_PTR(-EINVAL);
+
 	scoped_guard(spinlock, &parent->children_lock) {
 		sg = gmap_find_shadow(parent, asce, edat_level);
 		if (sg) {
-- 
2.53.0
Re: [PATCH v2 6/8] KVM: s390: vsie: Fix unshadowing while shadowing
Posted by Janosch Frank 1 week, 3 days ago
On 3/20/26 17:15, Claudio Imbrenda wrote:
> If shadowing causes the shadow gmap to get unshadowed, exit early to

How can this happen?

> prevent an attempt to dereference the parent pointer, which at this
> point is NULL.
> 
> Opportunistically add some more checks to prevent NULL parents.
Re: [PATCH v2 6/8] KVM: s390: vsie: Fix unshadowing while shadowing
Posted by Claudio Imbrenda 1 week, 3 days ago
On Tue, 24 Mar 2026 15:52:02 +0100
Janosch Frank <frankja@linux.ibm.com> wrote:

> On 3/20/26 17:15, Claudio Imbrenda wrote:
> > If shadowing causes the shadow gmap to get unshadowed, exit early to  
> 
> How can this happen?

one possibility is if g2 maps g3 memory pages over the top-level table
of the g2 -> g3 asce

there are probably other cases I can't think of

> 
> > prevent an attempt to dereference the parent pointer, which at this
> > point is NULL.
> > 
> > Opportunistically add some more checks to prevent NULL parents.