* [PATCH v7 00/14] KVM: s390: Misc fixes
@ 2026-07-31 13:01 Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
` (13 more replies)
0 siblings, 14 replies; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
Fix a bunch of small issues that came up during the previous round of fixes.
They are mostly extremely unlikely races, but they should be fixed
nonetheless.
v6->v7
* Do not free SCA in kvm_arch_init_vm() if it was not allocated
* Remove a KVM_BUG_ON() that could still be triggered from userspace
with UCONTROL.
* Remove KVM_BUG_ON() if a memslot change could not be performed.
* Fence KVM_S390_INTERRUPT also for vCPUs for UCONTROL VMs.
* Drop the last patch. Will need a more complex fix, will be done in a
different series.
v5->v6
* Move the memory accesses in sca_ext_call_pending() and
sca_inject_ext_call() so that they only happen after the newly
introduced checks. Otherwise an out of bounds access was still possible.
* Completely fence the KVM_S390_INTERRUPT ioctl for UCONTROL VMs.
* Move page table updates from kvm_arch_commit_memory_region() to
kvm_arch_prepare_memory_region(), so that failures are not ignored.
v4->v5
* Improve / fix some comments
* Undo handle_mvpg_pei() changes
* cmma_d_count_pte() now clears the cmma_d bit, to avoid double counting
* Improve some patch descriptions
* Trigger KVM_BUG_ON() in sca_ext_call_pending() and
sca_inject_ext_call() if called on UCONTROL vCPUs
* Reshuffle the order of the patches to hopefully get fewer false
positives from sashiko
* Check and free cbrlo only if it's not zero
v3->v4
* Improve patch descriptions, add comments
* Use smp_store_release and smp_load_acquire in the first patch
* Multiple fixes in patch 4: potential NULL pointer dereference,
incorrect behaviour in low memory condition
* Rework patch 8 to use scope-based cleanup instead of gotos.
* Three new patches:
- KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory
- KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
- KVM: s390: Fix sca_clear_ext_call() for UCONTROL
v2->v3
* Use READ_ONCE to pair with WRITE_ONCE in the first patch
* Fix leaking PGM_ADDRESSING also in kvm_s390_keyop() and related functions
* Fix and improve commit messages
* Use slots_arch_lock instead of slots_lock for ESSA operations
* Use normal spin_{,un}lock() functions instead of scoped_guard to avoid
mixing the two styles
* Use the newly introduced vcpu->arch.initialized to determine whether the
SCA entry needs to be cleared
* Improve handling of -EINTR; handle_mvpg_pei() needed some refactoring to
deal with it properly
* Three new patches:
- Free the mmu cache when kvm_arch_vcpu_create() fails
- Fix ordering when adding to SCA
- Fix cleanup in kvm_s390_pv_create_cpu()
v1->v2
* Drop some patches that have been picked upstream in the meantime.
* Drop patch 3, as it was trying to fix a bug that does not exist
* Avoid the NULL gmap dereference by using a flag
* Fix the return value of kvm_s390_[gp]et_skeys too
* Use kvm->slots_arch_lock instead of kvm->slots_lock for CMMA and ESSA
handling, to avoid potential deadlocks with the RCU.
* Three new patches to fix other issues that came out while fixing the
other issues
Claudio Imbrenda (14):
KVM: s390: Fix unlikely NULL gmap dereference
KVM: s390: Do not free SCA if it was not allocated
KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
KVM: s390: Fix overclearing ESCA in case of error
KVM: s390: ucontrol: Fix sca_clear_ext_call()
KVM: s390: Fix leaking of PGM_ADDRESSING to userspace
KVM: s390: Fix race in __do_essa()
KVM: s390: cmma: Fix dirty tracking when removing memslot
KVM: s390: ucontrol: Add missing locking around gmap_remove_child()
KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails
KVM: s390: Return -EINTR if a signal is pending while faulting-in
KVM: s390: Fix ordering when adding to SCA
KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu()
KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory
arch/s390/include/asm/kvm_host.h | 1 +
arch/s390/kvm/dat.c | 23 +++--
arch/s390/kvm/dat.h | 2 +-
arch/s390/kvm/faultin.c | 6 +-
arch/s390/kvm/interrupt.c | 19 +++--
arch/s390/kvm/kvm-s390.c | 139 ++++++++++++++++++++-----------
arch/s390/kvm/priv.c | 10 ++-
arch/s390/kvm/pv.c | 43 +++++-----
8 files changed, 153 insertions(+), 90 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:20 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated Claudio Imbrenda
` (12 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
When creating a new vCPU, kvm_vm_ioctl_create_vcpu() will call
kvm_arch_vcpu_postcreate() after the file descriptor for the new vCPU
has been created. The new file descriptor has not been returned yet,
but a malicious userspace program could try to guess it.
If a malicious userspace program manages to start the newly created vCPU
before kvm_arch_vcpu_postcreate() is called, __vcpu_run() will try to
dereference vcpu->arch.gmap and trigger a NULL pointer dereference.
Fix this by adding a new field to struct kvm_vcpu_arch to keep track of
the initialization status of the vCPU. Refuse to run a vCPU that is not
fully initialized.
Fixes: dafd032a15f8 ("KVM: s390: move vcpu specific initalization to a later point")
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
---
arch/s390/include/asm/kvm_host.h | 1 +
arch/s390/kvm/kvm-s390.c | 11 +++++++++++
2 files changed, 12 insertions(+)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index eaa34c5bd3c1..edf75b6ad20c 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -440,6 +440,7 @@ struct kvm_vcpu_arch {
bool skey_enabled;
/* Indicator if the access registers have been loaded from guest */
bool acrs_loaded;
+ bool initialized;
struct kvm_s390_pv_vcpu pv;
union diag318_info diag318_info;
struct kvm_s390_mmu_cache *mc;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 150b5dd2170e..f86b4b0b356f 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3613,6 +3613,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
vcpu->kvm->arch.user_operexec)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
+
+ /* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */
+ smp_store_release(&vcpu->arch.initialized, true);
}
static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
@@ -5039,6 +5042,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
return -EINVAL;
+ /* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
+ if (!smp_load_acquire(&vcpu->arch.initialized))
+ return -EINVAL;
+
vcpu_load(vcpu);
if (guestdbg_exit_pending(vcpu)) {
@@ -5523,6 +5530,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
long r;
u16 rc, rrc;
+ /* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
+ if (!smp_load_acquire(&vcpu->arch.initialized))
+ return -EINVAL;
+
vcpu_load(vcpu);
switch (ioctl) {
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:13 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() Claudio Imbrenda
` (11 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
If VM creation fails early in kvm_arch_init_vm(), the cleanup code
tries to free up the SCA, even though the address is 0. Due to using
free_pages_exact(), only the first page is skipped, accidentally
freeing pages 1, 2, and 3.
Fix by checking whether the pointer is NULL before attempting to free
the SCA in sca_dispose().
Fixes: e72753ed1267 ("KVM: s390: Use ESCA instead of BSCA at VM init")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/kvm-s390.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index f86b4b0b356f..1b3290a5ad1a 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3247,7 +3247,8 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
static void sca_dispose(struct kvm *kvm)
{
- free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
+ if (kvm->arch.sca)
+ free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
kvm->arch.sca = NULL;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error Claudio Imbrenda
` (10 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
In some cases kvm_s390_vcpu_unsetup_cmma() can be called with a 0
cbrlo; in such cases, if running with V != R, free_page() will attempt
to free physical page 0.
Fix by freeing cbrlo only if it's non-zero.
Fixes: b31605c12f4e ("KVM: s390: make cmma usage conditionally")
Fixes: 29b40f105ec8 ("KVM: s390: protvirt: Add initial vm and cpu lifecycle handling")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/kvm-s390.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 1b3290a5ad1a..9be27db0a21e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3678,7 +3678,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
{
- free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
+ if (vcpu->arch.sie_block->cbrlo)
+ free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
vcpu->arch.sie_block->cbrlo = 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (2 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:33 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() Claudio Imbrenda
` (9 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
If an attempt is made to create a vCPU with an already existing ID,
the duplicated vCPU will be destroyed. When destroying a vCPU, its
ESCA entry will be cleared. In the above scenario, the spurious
duplicate vCPU is destroyed, but the ESCA entry corresponding to the
original vCPU is cleared.
Fix by skipping clearing the ESCA entry if the vCPU creation was not
successful, i.e. if the pointer to the ESCA in the state description is
not set.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
---
arch/s390/kvm/interrupt.c | 2 +-
arch/s390/kvm/kvm-s390.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 9e3e6b0d72ad..2acdff130fa6 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -86,7 +86,7 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
- if (!kvm_s390_use_sca_entries())
+ if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
return;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 9be27db0a21e..5b2727d7dfd1 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3462,7 +3462,7 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
- if (!kvm_s390_use_sca_entries())
+ if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
return;
clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call()
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (3 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:19 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace Claudio Imbrenda
` (8 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
When cleaning up a UCONTROL VM, sca_clear_ext_call() will touch memory
outside of the allocated ESCA block, and UCONTROL VMs don't even use
ESCA.
Fix by not touching ESCA for UCONTROL VMs, and fence the
KVM_S390_INTERRUPT ioctl altogether.
Opportunistically add checks in sca_ext_call_pending() and
sca_inject_ext_call() to make sure UCONTROL VMs won't call those
functions ever.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: 7d43bafcff17 ("KVM: s390: Make provisions for ESCA utilization")
---
arch/s390/kvm/interrupt.c | 19 ++++++++++++++-----
arch/s390/kvm/kvm-s390.c | 5 +++++
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 2acdff130fa6..9db68e3ac178 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -45,13 +45,16 @@ static struct kvm_s390_gib *gib;
static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+ union esca_sigp_ctrl sigp_ctrl;
if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
return 0;
+ if (kvm_is_ucontrol(vcpu->kvm))
+ return 0;
BUG_ON(!kvm_s390_use_sca_entries());
+ sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
if (src_id)
*src_id = sigp_ctrl.scn;
@@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
{
- struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
+ struct esca_block *sca = vcpu->kvm->arch.sca;
+ union esca_sigp_ctrl *sigp_ctrl;
int expect, rc;
BUG_ON(!kvm_s390_use_sca_entries());
+ if (KVM_BUG_ON(kvm_is_ucontrol(vcpu->kvm), vcpu->kvm))
+ return -EINVAL;
+ sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
old_val = READ_ONCE(*sigp_ctrl);
old_val.c = 0;
@@ -84,10 +90,13 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+ union esca_sigp_ctrl *sigp_ctrl;
- if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
+ if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized || kvm_is_ucontrol(vcpu->kvm))
return;
+
+ /* Initialize after the above check, to prevent going out of bounds */
+ sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
WRITE_ONCE(sigp_ctrl->value, 0);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 5b2727d7dfd1..21574f57be72 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -2934,6 +2934,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
case KVM_S390_INTERRUPT: {
struct kvm_s390_interrupt s390int;
+ r = -EINVAL;
+ if (kvm_is_ucontrol(kvm))
+ break;
r = -EFAULT;
if (copy_from_user(&s390int, argp, sizeof(s390int)))
break;
@@ -5456,6 +5459,8 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
struct kvm_s390_interrupt s390int;
struct kvm_s390_irq s390irq = {};
+ if (kvm_is_ucontrol(vcpu->kvm))
+ return -EINVAL;
if (copy_from_user(&s390int, argp, sizeof(s390int)))
return -EFAULT;
if (s390int_to_s390irq(&s390int, &s390irq))
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (4 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:24 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 07/14] KVM: s390: Fix race in __do_essa() Claudio Imbrenda
` (7 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
If kvm_s390_set_cmma_bits() is asked to set CMMA values outside of a
memslot, PGM_ADDRESSING (5) is returned, instead of a negative error
value.
Same issue with kvm_s390_{g,s}et_skeys(), kvm_s390_keyop(), and
dat_reset_reference_bit().
Fix by returning -EFAULT whenever the return value would be > 0, which
is consistent with the behaviour before the gmap rewrite.
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/dat.c | 16 ++++++++++------
arch/s390/kvm/dat.h | 2 +-
arch/s390/kvm/kvm-s390.c | 16 ++++++++--------
arch/s390/kvm/priv.c | 5 +++--
4 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/arch/s390/kvm/dat.c b/arch/s390/kvm/dat.c
index ed4259d17629..171b61959908 100644
--- a/arch/s390/kvm/dat.c
+++ b/arch/s390/kvm/dat.c
@@ -755,13 +755,15 @@ int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gf
return rc;
}
-int dat_reset_reference_bit(union asce asce, gfn_t gfn)
+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)
{
union pgste pgste, old;
union crste *crstep;
union pte *ptep;
int rc;
+ skey->skey = 0;
+
rc = dat_entry_walk(NULL, gfn, asce, DAT_WALK_ANY, TABLE_TYPE_PAGE_TABLE, &crstep, &ptep);
if (rc)
return rc;
@@ -771,21 +773,23 @@ int dat_reset_reference_bit(union asce asce, gfn_t gfn)
if (!crste.h.fc || !crste.s.fc1.pr)
return 0;
- return page_reset_referenced(large_crste_to_phys(*crstep, gfn));
+ skey->skey = page_reset_referenced(large_crste_to_phys(*crstep, gfn)) << 1;
+ return 0;
}
old = pgste_get_lock(ptep);
pgste = old;
if (!ptep->h.i) {
- rc = page_reset_referenced(pte_origin(*ptep));
- pgste.hr = rc >> 1;
+ skey->skey = page_reset_referenced(pte_origin(*ptep)) << 1;
+ pgste.hr = skey->r;
}
- rc |= (pgste.gr << 1) | pgste.gc;
+ skey->r |= pgste.gr;
+ skey->c |= pgste.gc;
pgste.gr = 0;
dat_update_ptep_sd(old, pgste, ptep);
pgste_set_unlock(ptep, pgste);
- return rc;
+ return 0;
}
static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
diff --git a/arch/s390/kvm/dat.h b/arch/s390/kvm/dat.h
index fad605305e05..141ee7b9f019 100644
--- a/arch/s390/kvm/dat.h
+++ b/arch/s390/kvm/dat.h
@@ -537,7 +537,7 @@ int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gf
union skey skey, bool nq);
int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,
union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);
-int dat_reset_reference_bit(union asce asce, gfn_t gfn);
+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);
long dat_reset_skeys(union asce asce, gfn_t start);
unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 21574f57be72..e162efaa35b8 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
switch (op) {
case KVM_S390_KEYOP_SSKE:
r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
- if (r >= 0)
+ if (r == 0 || r == 1)
return skey.skey;
break;
case KVM_S390_KEYOP_ISKE:
@@ -580,14 +580,14 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
return skey.skey;
break;
case KVM_S390_KEYOP_RRBE:
- r = dat_reset_reference_bit(asce, gfn);
- if (r > 0)
- return r << 1;
+ r = dat_reset_reference_bit(asce, gfn, &skey);
+ if (!r)
+ return skey.skey;
break;
default:
return -EINVAL;
}
- return r;
+ return r > 0 ? -EFAULT : r;
}
/* Section: device related */
@@ -2214,7 +2214,7 @@ static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
}
kvfree(keys);
- return r;
+ return r <= 0 ? r : -EFAULT;
}
static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
@@ -2276,7 +2276,7 @@ static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
kvm_s390_free_mmu_cache(mc);
out:
kvfree(keys);
- return r;
+ return r <= 0 ? r : -EFAULT;
}
/*
@@ -2386,7 +2386,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
- return r;
+ return r <= 0 ? r : -EFAULT;
}
/**
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index ad0ddc433a73..ea5a99537346 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -289,6 +289,7 @@ static int handle_iske(struct kvm_vcpu *vcpu)
static int handle_rrbe(struct kvm_vcpu *vcpu)
{
unsigned long gaddr;
+ union skey skey;
int reg1, reg2;
int rc;
@@ -307,12 +308,12 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
- rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr));
+ rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr), &skey);
if (rc > 0)
return kvm_s390_inject_program_int(vcpu, rc);
if (rc < 0)
return rc;
- kvm_s390_set_psw_cc(vcpu, rc);
+ kvm_s390_set_psw_cc(vcpu, (skey.skey >> 1) & 3);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 07/14] KVM: s390: Fix race in __do_essa()
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (5 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:14 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot Claudio Imbrenda
` (6 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
An unlikely race between __do_essa() and kvm_s390_vm_start_migration(),
kvm_s390_vm_stop_migration(), or dat_get_cmma() was possible.
Fix by locking kvm->slots_arch_lock. Since this is not a hot path, the
overhead of an additional mutex is negligible.
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/kvm-s390.c | 20 ++++++++++----------
arch/s390/kvm/priv.c | 5 +++--
2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e162efaa35b8..e5c5e9f61cb2 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1219,8 +1219,8 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
/*
* Must be called with kvm->srcu held to avoid races on memslots, and with
- * kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
- * and kvm_s390_get_cmma_bits().
+ * kvm->slots_arch_lock to avoid races with ourselves,
+ * kvm_s390_vm_stop_migration(), and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_start_migration(struct kvm *kvm)
{
@@ -1265,7 +1265,7 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
}
/*
- * Must be called with kvm->slots_lock to avoid races with ourselves,
+ * Must be called with kvm->slots_arch_lock to avoid races with ourselves,
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
@@ -1300,7 +1300,9 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
{
int res = -ENXIO;
- mutex_lock(&kvm->slots_lock);
+ guard(srcu)(&kvm->srcu);
+ guard(mutex)(&kvm->slots_arch_lock);
+
switch (attr->attr) {
case KVM_S390_VM_MIGRATION_START:
res = kvm_s390_vm_start_migration(kvm);
@@ -1311,7 +1313,6 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
default:
break;
}
- mutex_unlock(&kvm->slots_lock);
return res;
}
@@ -3001,9 +3002,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
- mutex_lock(&kvm->slots_lock);
- r = kvm_s390_get_cmma_bits(kvm, &args);
- mutex_unlock(&kvm->slots_lock);
+ scoped_guard(mutex, &kvm->slots_arch_lock)
+ r = kvm_s390_get_cmma_bits(kvm, &args);
if (!r) {
r = copy_to_user(argp, &args, sizeof(args));
if (r)
@@ -3017,9 +3017,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
- mutex_lock(&kvm->slots_lock);
+ mutex_lock(&kvm->slots_arch_lock);
r = kvm_s390_set_cmma_bits(kvm, &args);
- mutex_unlock(&kvm->slots_lock);
+ mutex_unlock(&kvm->slots_arch_lock);
break;
}
case KVM_S390_PV_COMMAND: {
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index ea5a99537346..b1ba24c346ef 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -1261,8 +1261,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
/* Retry the ESSA instruction */
kvm_s390_retry_instr(vcpu);
} else {
- scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
- i = __do_essa(vcpu, orc);
+ scoped_guard(mutex, &vcpu->kvm->slots_arch_lock)
+ scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
+ i = __do_essa(vcpu, orc);
if (i < 0)
return i;
/* Account for the possible extra cbrl entry */
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (6 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 07/14] KVM: s390: Fix race in __do_essa() Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:36 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() Claudio Imbrenda
` (5 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
When a memslot is removed, all ptes that mapped the slot are cleared or
even deallocated. If this happens while the system is in migration
mode, and if cmma-dirty pages are removed, the cmma-dirty counter will
not reflect reality.
Fix by appropriately decrementing the cmma-dirty counter when removing
a memslot.
Opportunistically improve kvm_arch_commit_memory_region() to use
__free() for the struct kvm_s390_mmu_cache.
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/dat.c | 7 ++++++-
arch/s390/kvm/kvm-s390.c | 25 +++++++++++++++++++++++--
2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/s390/kvm/dat.c b/arch/s390/kvm/dat.c
index 171b61959908..3f2d6e8902d7 100644
--- a/arch/s390/kvm/dat.c
+++ b/arch/s390/kvm/dat.c
@@ -850,6 +850,7 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
struct slot_priv *p = walk->priv;
union crste dummy = { .val = p->token };
union pte new_pte, pte = READ_ONCE(*ptep);
+ union pgste pgste;
new_pte = _PTE_TOK(dummy.tok.type, dummy.tok.par);
@@ -857,7 +858,11 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
if (pte.val == new_pte.val)
return 0;
- dat_ptep_xchg(ptep, new_pte, gfn, walk->asce, false);
+ pgste = pgste_get_lock(ptep);
+ pgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk->asce, false);
+ pgste.cmma_d = 0;
+ pgste_set_unlock(ptep, pgste);
+
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e5c5e9f61cb2..ba811f0673d1 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -5812,14 +5812,30 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
return 0;
}
+static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
+{
+ union pgste pgste;
+
+ pgste = pgste_get_lock(ptep);
+ if (pgste.cmma_d) {
+ pgste.cmma_d = 0;
+ atomic64_dec(walk->priv);
+ }
+ pgste_set_unlock(ptep, pgste);
+ return 0;
+}
+
void kvm_arch_commit_memory_region(struct kvm *kvm,
struct kvm_memory_slot *old,
const struct kvm_memory_slot *new,
enum kvm_mr_change change)
{
- struct kvm_s390_mmu_cache *mc = NULL;
+ const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };
+ struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc = 0;
+ guard(mutex)(&kvm->slots_arch_lock);
+
if (change == KVM_MR_FLAGS_ONLY)
return;
@@ -5830,6 +5846,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
}
scoped_guard(write_lock, &kvm->mmu_lock) {
+ if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
+ _dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
+ kvm->arch.gmap->asce, &ops, DAT_WALK_IGN_HOLES,
+ &kvm->arch.cmma_dirty_pages);
+ }
+
switch (change) {
case KVM_MR_DELETE:
rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
@@ -5851,7 +5873,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
out:
if (rc)
pr_warn("failed to commit memory region\n");
- kvm_s390_free_mmu_cache(mc);
return;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child()
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (7 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:35 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails Claudio Imbrenda
` (4 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
gmap_remove_child() needs to be called while holding the children_lock
of the parent gmap. This was not the case in the error handling path of
kvm_arch_vcpu_create() for UCONTROL guests.
Fix by adding the missing lock.
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/kvm-s390.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ba811f0673d1..2741ca323ede 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3875,7 +3875,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
out_ucontrol_uninit:
if (kvm_is_ucontrol(vcpu->kvm)) {
+ spin_lock(&vcpu->kvm->arch.gmap->children_lock);
gmap_remove_child(vcpu->arch.gmap);
+ spin_unlock(&vcpu->kvm->arch.gmap->children_lock);
vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
}
out_free_sie_block:
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (8 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:11 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in Claudio Imbrenda
` (3 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
The mmu cache is the first thing that is allocated in
kvm_arch_vcpu_create(), but in case of failure it was not freed.
Fix by freeing the mmu cache in case of failure.
Refactor kvm_arch_vcpu_create() to use scope-based cleanup instead of
gotos.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
---
arch/s390/kvm/kvm-s390.c | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2741ca323ede..9b8a35e7dc82 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3800,21 +3800,21 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
return 0;
}
+DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))
+
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{
- struct sie_page *sie_page;
+ struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
+ struct sie_page *sie_page __free(sie_page) = NULL;
int rc;
BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
- vcpu->arch.mc = kvm_s390_new_mmu_cache();
- if (!vcpu->arch.mc)
+ mc = kvm_s390_new_mmu_cache();
+ if (!mc)
return -ENOMEM;
sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL_ACCOUNT);
- if (!sie_page) {
- kvm_s390_free_mmu_cache(vcpu->arch.mc);
- vcpu->arch.mc = NULL;
+ if (!sie_page)
return -ENOMEM;
- }
vcpu->arch.sie_block = &sie_page->sie_block;
vcpu->arch.sie_block->itdba = virt_to_phys(&sie_page->itdb);
@@ -3856,10 +3856,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
if (kvm_is_ucontrol(vcpu->kvm)) {
- rc = -ENOMEM;
vcpu->arch.gmap = gmap_new_child(vcpu->kvm->arch.gmap, -1UL);
if (!vcpu->arch.gmap)
- goto out_free_sie_block;
+ return -ENOMEM;
}
VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%p, sie block at 0x%p",
@@ -3867,22 +3866,19 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
rc = kvm_s390_vcpu_setup(vcpu);
- if (rc)
- goto out_ucontrol_uninit;
+ if (rc) {
+ if (kvm_is_ucontrol(vcpu->kvm)) {
+ scoped_guard(spinlock, &vcpu->kvm->arch.gmap->children_lock)
+ gmap_remove_child(vcpu->arch.gmap);
+ vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
+ }
+ return rc;
+ }
+ vcpu->arch.mc = no_free_ptr(mc);
+ sie_page = NULL;
kvm_s390_update_topology_change_report(vcpu->kvm, 1);
return 0;
-
-out_ucontrol_uninit:
- if (kvm_is_ucontrol(vcpu->kvm)) {
- spin_lock(&vcpu->kvm->arch.gmap->children_lock);
- gmap_remove_child(vcpu->arch.gmap);
- spin_unlock(&vcpu->kvm->arch.gmap->children_lock);
- vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
- }
-out_free_sie_block:
- free_page((unsigned long)(vcpu->arch.sie_block));
- return rc;
}
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (9 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:20 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA Claudio Imbrenda
` (2 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
If a fatal signal is pending while trying to fault-in a page, return
-EINTR instead of -EAGAIN.
Also fix unpack_one() to handle -EINTR properly.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: e907ae530133 ("KVM: s390: Add helper functions for fault handling")
---
arch/s390/kvm/faultin.c | 6 +++---
arch/s390/kvm/pv.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/s390/kvm/faultin.c b/arch/s390/kvm/faultin.c
index fee80047bd94..3cc45f7f5b2d 100644
--- a/arch/s390/kvm/faultin.c
+++ b/arch/s390/kvm/faultin.c
@@ -91,9 +91,9 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
/* Access outside memory, addressing exception. */
if (is_noslot_pfn(f->pfn))
return PGM_ADDRESSING;
- /* Signal pending: try again. */
- if (f->pfn == KVM_PFN_ERR_SIGPENDING)
- return -EAGAIN;
+ /* Fatal signal pending: bail out. */
+ if (is_sigpending_pfn(f->pfn))
+ return -EINTR;
/* Check if it's read-only memory; don't try to actually handle that case. */
if (f->pfn == KVM_PFN_ERR_RO_FAULT)
return -EOPNOTSUPP;
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 1beacc841ca8..dc204b521052 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -809,7 +809,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,
return -EAGAIN;
}
- if (ret && ret != -EAGAIN)
+ if (ret && ret != -EAGAIN && ret != -EINTR)
KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x",
uvcb.gaddr, *rc, *rrc);
return ret;
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (10 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu() Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory Claudio Imbrenda
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
When adding a new vCPU to the SCA area, the validity bit in the MCN was
set before the pointer to the state description, potentially allowing
for a race.
Fix by setting the pointer before setting the bit.
Fixes: 14542a0a54c5 ("KVM: S390: Remove sca_lock")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
---
arch/s390/kvm/kvm-s390.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 9b8a35e7dc82..518a69c55e85 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3485,8 +3485,8 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
if (!kvm_s390_use_sca_entries())
return;
+ WRITE_ONCE(sca->cpu[vcpu->vcpu_id].sda, virt_to_phys(vcpu->arch.sie_block));
set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
- sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
}
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu()
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (11 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory Claudio Imbrenda
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
If creating a protected vCPU in kvm_s390_pv_create_cpu() fails,
kvm_s390_pv_destroy_cpu() was called, which checks whether the vCPU has
a PV handle and exits doing nothing otherwise. At that point, due to
not having created the protected vCPU, the PV handle will not be set,
and kvm_s390_pv_destroy_cpu() will do nothing, thus leaking the
allocated memory.
Fix by factoring out the code to free and reset a PV vCPU; call it from
kvm_s390_pv_destroy_cpu() and kvm_s390_pv_create_cpu().
Opportunistically fix the return value of kvm_s390_pv_destroy_cpu() in
case of errors: return -EIO instead if EIO.
Fixes: d4074324b07a ("KVM: s390: pv: avoid double free of sida page")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/pv.c | 41 +++++++++++++++++++++--------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index dc204b521052..b02e0159d3cd 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -244,6 +244,24 @@ static void kvm_s390_clear_pv_state(struct kvm *kvm)
kvm->arch.pv.stor_var = NULL;
}
+static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)
+{
+ if (free_stor_base)
+ free_pages(vcpu->arch.pv.stor_base, get_order(uv_info.guest_cpu_stor_len));
+ free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
+ vcpu->arch.sie_block->pv_handle_cpu = 0;
+ vcpu->arch.sie_block->pv_handle_config = 0;
+ memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
+ vcpu->arch.sie_block->sdf = 0;
+ /*
+ * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
+ * Use the reset value of gbea to avoid leaking the kernel pointer of
+ * the just freed sida.
+ */
+ vcpu->arch.sie_block->gbea = 1;
+ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+}
+
int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
{
int cc;
@@ -258,24 +276,9 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc);
/* Intended memory leak for something that should never happen. */
- if (!cc)
- free_pages(vcpu->arch.pv.stor_base,
- get_order(uv_info.guest_cpu_stor_len));
-
- free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
- vcpu->arch.sie_block->pv_handle_cpu = 0;
- vcpu->arch.sie_block->pv_handle_config = 0;
- memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
- vcpu->arch.sie_block->sdf = 0;
- /*
- * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
- * Use the reset value of gbea to avoid leaking the kernel pointer of
- * the just freed sida.
- */
- vcpu->arch.sie_block->gbea = 1;
- kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+ kvm_s390_pv_dispose_cpu(vcpu, !cc);
- return cc ? EIO : 0;
+ return cc ? -EIO : 0;
}
int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
@@ -319,9 +322,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
uvcb.header.rrc);
if (cc) {
- u16 dummy;
-
- kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
+ kvm_s390_pv_dispose_cpu(vcpu, true);
return -EIO;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
` (12 preceding siblings ...)
2026-07-31 13:01 ` [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu() Claudio Imbrenda
@ 2026-07-31 13:01 ` Claudio Imbrenda
2026-07-31 13:32 ` sashiko-bot
13 siblings, 1 reply; 29+ messages in thread
From: Claudio Imbrenda @ 2026-07-31 13:01 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, linux-s390, borntraeger, frankja, david, seiden, nrb,
schlameuss, gra
When low on memory, kvm_arch_commit_memory_region() might not perform
the required action completely, and instead just print a warning and
return. This allows the VM to continue running with an inconsistent
state.
Fix by refilling the struct kvm_s390_mmu_cache and trying again. A true
failure only happens if the refill fails, or if the cache cannot be
allocated at all; in such case print a warning and kill the VM. Such a
failure cannot currently happen.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
---
arch/s390/kvm/kvm-s390.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 518a69c55e85..fd8badb0d571 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -5830,7 +5830,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
{
const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
- int rc = 0;
+ int rc = -ENOMEM;
guard(mutex)(&kvm->slots_arch_lock);
@@ -5838,11 +5838,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
return;
mc = kvm_s390_new_mmu_cache();
- if (!mc) {
- rc = -ENOMEM;
+ if (!mc)
goto out;
- }
-
+retry:
scoped_guard(write_lock, &kvm->mmu_lock) {
if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
_dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
@@ -5865,9 +5863,15 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
case KVM_MR_FLAGS_ONLY:
break;
default:
+ rc = 0;
WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
}
}
+ if (rc == -ENOMEM) {
+ rc = kvm_s390_mmu_cache_topup(mc);
+ if (!rc)
+ goto retry;
+ }
out:
if (rc)
pr_warn("failed to commit memory region\n");
--
2.55.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails
2026-07-31 13:01 ` [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails Claudio Imbrenda
@ 2026-07-31 13:11 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:11 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Alexander Gordeev, kvm, Heiko Carstens, Vasily Gorbik, linux-s390
> The mmu cache is the first thing that is allocated in
> kvm_arch_vcpu_create(), but in case of failure it was not freed.
>
> Fix by freeing the mmu cache in case of failure.
>
> Refactor kvm_arch_vcpu_create() to use scope-based cleanup instead of
> gotos.
>
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=10
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated
2026-07-31 13:01 ` [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated Claudio Imbrenda
@ 2026-07-31 13:13 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:13 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Vasily Gorbik, kvm, Alexander Gordeev, Heiko Carstens, linux-s390
> If VM creation fails early in kvm_arch_init_vm(), the cleanup code
> tries to free up the SCA, even though the address is 0. Due to using
> free_pages_exact(), only the first page is skipped, accidentally
> freeing pages 1, 2, and 3.
>
> Fix by checking whether the pointer is NULL before attempting to free
> the SCA in sca_dispose().
>
> Fixes: e72753ed1267 ("KVM: s390: Use ESCA instead of BSCA at VM init")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=2
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 07/14] KVM: s390: Fix race in __do_essa()
2026-07-31 13:01 ` [PATCH v7 07/14] KVM: s390: Fix race in __do_essa() Claudio Imbrenda
@ 2026-07-31 13:14 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:14 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Heiko Carstens, Vasily Gorbik, kvm, linux-s390, Alexander Gordeev
> An unlikely race between __do_essa() and kvm_s390_vm_start_migration(),
> kvm_s390_vm_stop_migration(), or dat_get_cmma() was possible.
>
> Fix by locking kvm->slots_arch_lock. Since this is not a hot path, the
> overhead of an additional mutex is negligible.
>
> Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=7
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call()
2026-07-31 13:01 ` [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() Claudio Imbrenda
@ 2026-07-31 13:19 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:19 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Vasily Gorbik, linux-s390, Alexander Gordeev, Heiko Carstens, kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Host userspace and malicious guests can trigger a KVM_BUG_ON (WARN_ON_ONCE) by injecting an external call into a UCONTROL VM.
- [High] Fencing the KVM_S390_INTERRUPT ioctl entirely for UCONTROL VMs breaks backwards compatibility.
--
--- Patch [5]: [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() ---
commit 22db5ca2b2a238d3fc521f6c7e38a951435c51a0
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: ucontrol: Fix sca_clear_ext_call()
When cleaning up a UCONTROL VM, sca_clear_ext_call() will touch memory
outside of the allocated ESCA block, and UCONTROL VMs don't even use
ESCA. This commit stops UCONTROL VMs from touching ESCA, fences the
KVM_S390_INTERRUPT ioctl, and adds checks to other ESCA paths.
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 2acdff130fa6c..9db68e3ac178f 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
[ ... ]
> @@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
>
> static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
> {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
> union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + union esca_sigp_ctrl *sigp_ctrl;
> int expect, rc;
>
> BUG_ON(!kvm_s390_use_sca_entries());
> + if (KVM_BUG_ON(kvm_is_ucontrol(vcpu->kvm), vcpu->kvm))
> + return -EINVAL;
[Severity: High]
Can a malicious guest or unprivileged host userspace process trigger this
assertion?
It appears UCONTROL VMs can still reach sca_inject_ext_call() through other
unfenced paths. For example, host userspace can call the KVM_S390_IRQ ioctl
with KVM_S390_INT_EXTERNAL_CALL without being fenced, as the UCONTROL check
was only added to KVM_S390_INTERRUPT.
The ioctl flows through:
kvm_arch_vcpu_unlocked_ioctl()
case KVM_S390_IRQ:
kvm_s390_inject_vcpu()
do_inject_vcpu()
sca_inject_ext_call()
Similarly, a guest executing a SIGP EXTERNAL CALL instruction can intercept
to __sigp_external_call(), which also calls kvm_s390_inject_vcpu() and will
ultimately hit this KVM_BUG_ON.
Would it be safer to return an error without the KVM_BUG_ON to prevent
a host denial of service if the system is configured with panic_on_warn?
[ ... ]
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 5b2727d7dfd12..21574f57be72e 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2934,6 +2934,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> case KVM_S390_INTERRUPT: {
> struct kvm_s390_interrupt s390int;
>
> + r = -EINVAL;
> + if (kvm_is_ucontrol(kvm))
> + break;
[Severity: High]
Does completely fencing the KVM_S390_INTERRUPT ioctl for UCONTROL VMs
cause an ABI regression for older userspace tools?
If existing userspace relies on KVM_S390_INTERRUPT to inject non-external
interrupts (such as KVM_S390_PROGRAM_INT), this unconditional check would
cause those injections to fail with -EINVAL, potentially breaking existing
functionality.
Could this check be restricted to only rejecting the specific interrupt
types that rely on ESCA?
> r = -EFAULT;
> if (copy_from_user(&s390int, argp, sizeof(s390int)))
> break;
[ ... ]
> @@ -5456,6 +5459,8 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
> struct kvm_s390_interrupt s390int;
> struct kvm_s390_irq s390irq = {};
>
> + if (kvm_is_ucontrol(vcpu->kvm))
> + return -EINVAL;
[Severity: High]
Is this also prone to the same backwards compatibility regression mentioned
above for vCPU-level interrupt injections?
> if (copy_from_user(&s390int, argp, sizeof(s390int)))
> return -EFAULT;
> if (s390int_to_s390irq(&s390int, &s390irq))
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=5
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference
2026-07-31 13:01 ` [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
@ 2026-07-31 13:20 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:20 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Heiko Carstens, linux-s390, Vasily Gorbik, Alexander Gordeev, kvm
> When creating a new vCPU, kvm_vm_ioctl_create_vcpu() will call
> kvm_arch_vcpu_postcreate() after the file descriptor for the new vCPU
> has been created. The new file descriptor has not been returned yet,
> but a malicious userspace program could try to guess it.
>
> If a malicious userspace program manages to start the newly created vCPU
> before kvm_arch_vcpu_postcreate() is called, __vcpu_run() will try to
> dereference vcpu->arch.gmap and trigger a NULL pointer dereference.
>
> Fix this by adding a new field to struct kvm_vcpu_arch to keep track of
> the initialization status of the vCPU. Refuse to run a vCPU that is not
> fully initialized.
>
> Fixes: dafd032a15f8 ("KVM: s390: move vcpu specific initalization to a later point")
> Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in
2026-07-31 13:01 ` [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in Claudio Imbrenda
@ 2026-07-31 13:20 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:20 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: linux-s390, Heiko Carstens, Alexander Gordeev, Vasily Gorbik, kvm
> If a fatal signal is pending while trying to fault-in a page, return
> -EINTR instead of -EAGAIN.
>
> Also fix unpack_one() to handle -EINTR properly.
>
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=11
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA
2026-07-31 13:01 ` [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA Claudio Imbrenda
@ 2026-07-31 13:21 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:21 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: kvm, Vasily Gorbik, linux-s390, Heiko Carstens, Alexander Gordeev
> When adding a new vCPU to the SCA area, the validity bit in the MCN was
> set before the pointer to the state description, potentially allowing
> for a race.
>
> Fix by setting the pointer before setting the bit.
>
> Fixes: 14542a0a54c5 ("KVM: S390: Remove sca_lock")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=12
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
2026-07-31 13:01 ` [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() Claudio Imbrenda
@ 2026-07-31 13:21 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:21 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: linux-s390, Vasily Gorbik, kvm, Alexander Gordeev, Heiko Carstens
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The `kvm_arch_vcpu_create` function leaks the MMU cache on error paths.
- [High] Memory leak of protected VCPU storage base (`stor_base`) and SIDA pages when `uv_call` fails in `kvm_s390_pv_create_cpu()`.
--
--- Patch [3]: [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() ---
commit a13468185076d541edaaa78721cdc3f5e4915351
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
This patch fixes an issue in kvm_s390_vcpu_unsetup_cmma() where a 0
cbrlo could cause free_page() to attempt to free physical page 0 when
running with V != R. It adds a check to only free cbrlo if it is non-zero.
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 1b3290a5ad1ae..9be27db0a21e6 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -3678,7 +3678,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
>
> void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
> {
> - free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
> + if (vcpu->arch.sie_block->cbrlo)
> + free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
> vcpu->arch.sie_block->cbrlo = 0;
> }
>
[Severity: High]
This isn't a regression introduced by this patch, but the kvm_arch_vcpu_create
function appears to leak the MMU cache on error paths:
arch/s390/kvm/kvm-s390.c:kvm_arch_vcpu_create() {
...
if (kvm_is_ucontrol(vcpu->kvm)) {
rc = -ENOMEM;
vcpu->arch.gmap = gmap_new_child(vcpu->kvm->arch.gmap, -1UL);
if (!vcpu->arch.gmap)
goto out_free_sie_block;
}
...
out_free_sie_block:
free_page((unsigned long)(vcpu->arch.sie_block));
return rc;
}
Can this leak vcpu->arch.mc? If vcpu creation fails after it is allocated,
the error path jumps to out_free_sie_block, but it doesn't seem to free
vcpu->arch.mc. Since kvm->created_vcpus is decremented upon failure,
could an unprivileged user repeatedly call KVM_CREATE_VCPU to trigger
failures and exhaust kernel memory?
[Severity: High]
This is a pre-existing regression, but there is also a potential memory leak
of the protected vcpu storage base (stor_base) and SIDA pages when
uv_call() fails:
arch/s390/kvm/pv.c:kvm_s390_pv_create_cpu() {
...
cc = uv_call(0, (u64)&uvcb);
...
if (cc) {
u16 dummy;
kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
return -EIO;
}
...
}
arch/s390/kvm/pv.c:kvm_s390_pv_destroy_cpu() {
...
if (!kvm_s390_pv_cpu_get_handle(vcpu))
return 0;
...
}
Since the handle is only set after a successful uv_call(), does the early
return in kvm_s390_pv_destroy_cpu() silently skip freeing
vcpu->arch.pv.stor_base and the sidad page? Could this be reached by a
user repeatedly calling KVM_CREATE_VCPU on a protected VM to trigger
failures, leading to a host denial of service?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=3
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu()
2026-07-31 13:01 ` [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu() Claudio Imbrenda
@ 2026-07-31 13:21 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:21 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: kvm, Alexander Gordeev, Heiko Carstens, Vasily Gorbik, linux-s390
> If creating a protected vCPU in kvm_s390_pv_create_cpu() fails,
> kvm_s390_pv_destroy_cpu() was called, which checks whether the vCPU has
> a PV handle and exits doing nothing otherwise. At that point, due to
> not having created the protected vCPU, the PV handle will not be set,
> and kvm_s390_pv_destroy_cpu() will do nothing, thus leaking the
> allocated memory.
>
> Fix by factoring out the code to free and reset a PV vCPU; call it from
> kvm_s390_pv_destroy_cpu() and kvm_s390_pv_create_cpu().
>
> Opportunistically fix the return value of kvm_s390_pv_destroy_cpu() in
> case of errors: return -EIO instead if EIO.
>
> Fixes: d4074324b07a ("KVM: s390: pv: avoid double free of sida page")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=13
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace
2026-07-31 13:01 ` [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace Claudio Imbrenda
@ 2026-07-31 13:24 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:24 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: linux-s390, Alexander Gordeev, kvm, Heiko Carstens, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Uninitialized stack variable `prev.zero` is leaked to userspace.
--
--- Patch [6]: [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace ---
commit ed708d75cfaadb270c9e236e10c87fa7cbbb9d4f
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: Fix leaking of PGM_ADDRESSING to userspace
This commit modifies KVM memory ioctls (such as setting CMMA bits or storage
keys) to return -EFAULT instead of a positive PGM_ADDRESSING error code when
addressing outside a memslot. This restores the expected behavior from before
the gmap rewrite.
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 21574f57be72e..e162efaa35b8f 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
> switch (op) {
> case KVM_S390_KEYOP_SSKE:
> r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
[Severity: High]
This is a pre-existing issue, but does dat_cond_set_storage_key() leak
uninitialized kernel stack memory to userspace here?
When the KVM_S390_KEYOP ioctl is called with KVM_S390_KEYOP_SSKE, it calls
dat_cond_set_storage_key(), which populates a local stack variable:
arch/s390/kvm/dat.c:dat_cond_set_storage_key() {
...
} else {
prev.acc = old.acc;
prev.fp = old.fp;
prev.c = old.gc;
prev.r = old.gr;
}
if (oldkey)
*oldkey = prev;
...
}
The 1-bit prev.zero bitfield is left uninitialized in this branch. The entire
1-byte union is then copied into *oldkey and returned to kvm_s390_keyop().
Could this value then be copied to userspace, successfully leaking 1 bit of
kernel stack memory?
> - if (r >= 0)
> + if (r == 0 || r == 1)
> return skey.skey;
> break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=6
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory
2026-07-31 13:01 ` [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory Claudio Imbrenda
@ 2026-07-31 13:32 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:32 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Vasily Gorbik, kvm, linux-s390, Heiko Carstens, Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Dropping `kvm->mmu_lock` during the retry loop allows vCPUs to fault in memory that will be subsequently overwritten, destroying guest storage keys.
Pre-existing issues:
- [Medium] Missing VM Kill on memory allocation failure leaves VM in an inconsistent state.
--
--- Patch [14]: [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory ---
commit 7328596d47af3b280bf92a137aeed10b8bbc3124
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory
When low on memory, kvm_arch_commit_memory_region() might not perform
the required action completely, leaving the VM in an inconsistent state.
This patch fixes it by refilling the struct kvm_s390_mmu_cache and trying
again.
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 518a69c55e85c..fd8badb0d571c 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
[ ... ]
> @@ -5838,11 +5838,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
> return;
>
> mc = kvm_s390_new_mmu_cache();
> - if (!mc) {
> - rc = -ENOMEM;
> + if (!mc)
> goto out;
> - }
> -
> +retry:
> scoped_guard(write_lock, &kvm->mmu_lock) {
> if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
> _dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
[Severity: High]
Since kvm_set_memory_region() makes the new memslot visible to vCPUs before
calling kvm_arch_commit_memory_region(), can a guest vCPU fault in the new
memslot while KVM is committing it?
If dat_create_slot() hits -ENOMEM due to a large memslot exhausting the MMU
cache during KVM_MR_CREATE, the retry loop drops kvm->mmu_lock to top up the
cache. During this unlocked window, the guest vCPU could install valid page
tables and storage keys.
When the retry loop reacquires the lock, it restarts dat_create_slot() from
the beginning of the memslot.
If this happens, wouldn't the callback blindly overwrite the guest's valid
PTEs with an empty token and permanently destroy the valid storage keys?
arch/s390/kvm/dat.c:_dat_slot_pte() {
...
pgste = pgste_get_lock(ptep);
pgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk->asce, false);
pgste.cmma_d = 0;
pgste_set_unlock(ptep, pgste);
...
}
[ ... ]
> @@ -5865,9 +5863,15 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
> case KVM_MR_FLAGS_ONLY:
> break;
> default:
> + rc = 0;
> WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
> }
> }
> + if (rc == -ENOMEM) {
> + rc = kvm_s390_mmu_cache_topup(mc);
> + if (!rc)
> + goto retry;
> + }
> out:
> if (rc)
> pr_warn("failed to commit memory region\n");
[Severity: Medium]
This is a pre-existing issue, but if kvm_s390_mmu_cache_topup() fails and
returns -ENOMEM when host memory is exhausted, doesn't the code fall through
to the out label and only log a warning via pr_warn?
The commit message states that such a failure should kill the VM. Does this
actually kill the VM, or does it leave the VM running with partially deleted
or corrupted memory slot mappings since no KVM kill mechanism is invoked
here?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=14
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error
2026-07-31 13:01 ` [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error Claudio Imbrenda
@ 2026-07-31 13:33 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:33 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Heiko Carstens, Vasily Gorbik, Alexander Gordeev, kvm, linux-s390
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Out-of-bounds ESCA entry accesses for ucontrol VMs due to bypassed vCPU ID limit check.
- [High] Memory leak of `vcpu->arch.mc` when `kvm_arch_vcpu_create` fails.
- [High] Memory leak in `kvm_s390_pv_create_cpu` error path allows malicious userspace to exhaust host memory (OOM).
--
--- Patch [4]: [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error ---
commit 3c41df2f29ed108f81950295bc782ec27a142a6b
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: Fix overclearing ESCA in case of error
> If an attempt is made to create a vCPU with an already existing ID,
> the duplicated vCPU will be destroyed.
[Severity: High]
This isn't a bug introduced by this patch, but does this duplicated vCPU
error path leak memory?
If a duplicated vCPU ID causes kvm_arch_vcpu_create() to fail, the error
path jumps to out_free_sie_block:
arch/s390/kvm/kvm-s390.c:kvm_arch_vcpu_create() {
...
out_free_sie_block:
free_page((unsigned long)(vcpu->arch.sie_block));
return rc;
}
This frees vcpu->arch.sie_block, but doesn't it leave vcpu->arch.mc
allocated? Can userspace intentionally exhaust host memory by repeatedly
creating duplicate vCPUs?
[Severity: High]
This is a pre-existing issue, but does a duplicate vCPU ID also trigger a
leak in the PV CPU creation error path?
If uv_call() fails due to the duplicate ID, kvm_s390_pv_create_cpu() calls
kvm_s390_pv_destroy_cpu():
arch/s390/kvm/pv.c:kvm_s390_pv_create_cpu() {
...
cc = uv_call(0, (u64)&uvcb);
if (cc) {
u16 dummy;
kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
return -EIO;
}
}
Because uv_call() failed, the secure CPU handle is unpopulated (0). The
destroy function checks this handle and returns early:
arch/s390/kvm/pv.c:kvm_s390_pv_destroy_cpu() {
if (!kvm_s390_pv_cpu_get_handle(vcpu))
return 0;
...
}
Does this skip the free_pages() calls, abandoning the allocated
vcpu->arch.pv.stor_base and sida_addr?
> When destroying a vCPU, its ESCA entry will be cleared. In the above
> scenario, the spurious duplicate vCPU is destroyed, but the ESCA entry
> corresponding to the original vCPU is cleared.
>
> Fix by skipping clearing the ESCA entry if the vCPU creation was not
> successful, i.e. if the pointer to the ESCA in the state description is
> not set.
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 9e3e6b0d72ad6..2acdff130fa6c 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -86,7 +86,7 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
> struct esca_block *sca = vcpu->kvm->arch.sca;
> union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
>
> - if (!kvm_s390_use_sca_entries())
> + if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
> return;
> kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
[Severity: Critical]
This isn't a bug introduced by this patch, but does this function perform
an out-of-bounds write for ucontrol VMs?
For ucontrol VMs, kvm_arch_vcpu_precreate() skips the sca_can_add_vcpu()
bounds check, allowing vcpu_id to reach up to 254 (KVM_MAX_VCPU_IDS - 1).
However, the ESCA block (sca->cpu) only contains 248 slots.
When a vcpu_id is >= 248, does the subsequent write to sigp_ctrl overwrite
adjacent memory?
arch/s390/kvm/interrupt.c:sca_clear_ext_call() {
...
WRITE_ONCE(sigp_ctrl->value, 0);
}
Similar out-of-bounds access happens in sca_inject_ext_call() during
cmpxchg(). Can an unprivileged user exploit this by creating a ucontrol VM
with vcpu_id >= 248 and triggering vCPU teardown?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=4
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child()
2026-07-31 13:01 ` [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() Claudio Imbrenda
@ 2026-07-31 13:35 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:35 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: kvm, Heiko Carstens, Vasily Gorbik, linux-s390, Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Memory leak of the VCPU MMU cache (`vcpu->arch.mc`) on `kvm_arch_vcpu_create()` error paths.
--
--- Patch [9]: [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() ---
commit f9a2b14fcbcb96b8df54e09c4777e2c6d45f939a
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
KVM: s390: ucontrol: Add missing locking around gmap_remove_child()
This commit adds missing locking around gmap_remove_child() in the error
handling path of kvm_arch_vcpu_create() for UCONTROL guests.
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index ba811f0673d10..2741ca323edea 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -3875,7 +3875,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
>
> out_ucontrol_uninit:
> if (kvm_is_ucontrol(vcpu->kvm)) {
> + spin_lock(&vcpu->kvm->arch.gmap->children_lock);
> gmap_remove_child(vcpu->arch.gmap);
> + spin_unlock(&vcpu->kvm->arch.gmap->children_lock);
> vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
> }
> out_free_sie_block:
[Severity: High]
This is a pre-existing issue, but does this error path leak the VCPU MMU
cache?
Looking at kvm_arch_vcpu_create() in arch/s390/kvm/kvm-s390.c, if a failure
happens and the code jumps to out_ucontrol_uninit or out_free_sie_block,
it appears to return the error code without calling kvm_s390_free_mmu_cache()
on vcpu->arch.mc.
Since the core KVM function kvm_vm_ioctl_create_vcpu() skips calling
kvm_arch_vcpu_destroy() when kvm_arch_vcpu_create() returns an error,
does this permanently leak the dynamically allocated cache object and its
elements?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=9
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot
2026-07-31 13:01 ` [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot Claudio Imbrenda
@ 2026-07-31 13:36 ` sashiko-bot
0 siblings, 0 replies; 29+ messages in thread
From: sashiko-bot @ 2026-07-31 13:36 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: Vasily Gorbik, linux-s390, Heiko Carstens, kvm, Alexander Gordeev
> When a memslot is removed, all ptes that mapped the slot are cleared or
> even deallocated. If this happens while the system is in migration
> mode, and if cmma-dirty pages are removed, the cmma-dirty counter will
> not reflect reality.
>
> Fix by appropriately decrementing the cmma-dirty counter when removing
> a memslot.
>
> Opportunistically improve kvm_arch_commit_memory_region() to use
> __free() for the struct kvm_s390_mmu_cache.
>
> Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731130138.173983-1-imbrenda@linux.ibm.com?part=8
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2026-07-31 13:36 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31 13:01 [PATCH v7 00/14] KVM: s390: Misc fixes Claudio Imbrenda
2026-07-31 13:01 ` [PATCH v7 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
2026-07-31 13:20 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 02/14] KVM: s390: Do not free SCA if it was not allocated Claudio Imbrenda
2026-07-31 13:13 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 03/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 04/14] KVM: s390: Fix overclearing ESCA in case of error Claudio Imbrenda
2026-07-31 13:33 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 05/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() Claudio Imbrenda
2026-07-31 13:19 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 06/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace Claudio Imbrenda
2026-07-31 13:24 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 07/14] KVM: s390: Fix race in __do_essa() Claudio Imbrenda
2026-07-31 13:14 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 08/14] KVM: s390: cmma: Fix dirty tracking when removing memslot Claudio Imbrenda
2026-07-31 13:36 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 09/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() Claudio Imbrenda
2026-07-31 13:35 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 10/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails Claudio Imbrenda
2026-07-31 13:11 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 11/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in Claudio Imbrenda
2026-07-31 13:20 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 12/14] KVM: s390: Fix ordering when adding to SCA Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 13/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu() Claudio Imbrenda
2026-07-31 13:21 ` sashiko-bot
2026-07-31 13:01 ` [PATCH v7 14/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory Claudio Imbrenda
2026-07-31 13:32 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox