Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: s390: vsie: Fix unshadowing while shadowing

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.

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")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

+19 -1
+9
arch/s390/kvm/gaccess.c
··· 1449 1449 pgste_set_unlock(ptep_h, pgste); 1450 1450 if (rc) 1451 1451 return rc; 1452 + if (!sg->parent) 1453 + return -EAGAIN; 1452 1454 1453 1455 newpte = _pte(f->pfn, 0, !p, 0); 1454 1456 if (!pgste_get_trylock(ptep, &pgste)) ··· 1478 1476 return rc; 1479 1477 1480 1478 do { 1479 + /* _gmap_crstep_xchg_atomic() could have unshadowed this shadow gmap */ 1480 + if (!sg->parent) 1481 + return -EAGAIN; 1481 1482 oldcrste = READ_ONCE(*host); 1482 1483 newcrste = _crste_fc1(f->pfn, oldcrste.h.tt, f->writable, !p); 1483 1484 newcrste.s.fc1.d |= oldcrste.s.fc1.d; ··· 1492 1487 if (!newcrste.h.p && !f->writable) 1493 1488 return -EOPNOTSUPP; 1494 1489 } while (!_gmap_crstep_xchg_atomic(sg->parent, host, oldcrste, newcrste, f->gfn, false)); 1490 + if (!sg->parent) 1491 + return -EAGAIN; 1495 1492 1496 1493 newcrste = _crste_fc1(f->pfn, oldcrste.h.tt, 0, !p); 1497 1494 gfn = gpa_to_gfn(raddr); ··· 1538 1531 entries[i - 1].pfn, i, entries[i - 1].writable); 1539 1532 if (rc) 1540 1533 return rc; 1534 + if (!sg->parent) 1535 + return -EAGAIN; 1541 1536 } 1542 1537 1543 1538 rc = dat_entry_walk(NULL, entries[LEVEL_MEM].gfn, sg->parent->asce, DAT_WALK_LEAF,
+10 -1
arch/s390/kvm/gmap.c
··· 1160 1160 static inline int __gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, struct gmap *sg, 1161 1161 struct gmap_protect_asce_top_level *context) 1162 1162 { 1163 + struct gmap *parent; 1163 1164 int rc, i; 1164 1165 1165 1166 guard(write_lock)(&sg->kvm->mmu_lock); ··· 1168 1167 if (kvm_s390_array_needs_retry_safe(sg->kvm, context->seq, context->f)) 1169 1168 return -EAGAIN; 1170 1169 1171 - scoped_guard(spinlock, &sg->parent->children_lock) { 1170 + parent = READ_ONCE(sg->parent); 1171 + if (!parent) 1172 + return -EAGAIN; 1173 + scoped_guard(spinlock, &parent->children_lock) { 1174 + if (READ_ONCE(sg->parent) != parent) 1175 + return -EAGAIN; 1172 1176 for (i = 0; i < CRST_TABLE_PAGES; i++) { 1173 1177 if (!context->f[i].valid) 1174 1178 continue; ··· 1255 1249 { 1256 1250 struct gmap *sg, *new; 1257 1251 int rc; 1252 + 1253 + if (WARN_ON(!parent)) 1254 + return ERR_PTR(-EINVAL); 1258 1255 1259 1256 scoped_guard(spinlock, &parent->children_lock) { 1260 1257 sg = gmap_find_shadow(parent, asce, edat_level);